python、OpenCV(cv2)、そしてNumPyを使って2枚の画像を合成する方法を記録します。
自分のやりたいことを調べた際、ある程度の記事が見つかるにもかかわらず知識がなく、意味が理解できないことが多くあったので、初心者でもわかりやすいように記述できるよう心がけます。
なお、筆者は画像関係について深く学んだことはなく、数学の知識は高校3年生レベル(又はそれ以下)です。
###参考にさせていただいた、サイトのURLを無断で記述させていただいております。
インターネットで調べたら出てくるので良いのではないかという認識ですが、問題がございましたら、直ちに修正させていただきます。
まず画像合成にあたり、筆者が試した方法を記述します。
(知識が全くない状態でしたので、インターネットで調べ、出てきたコードをくっつけたキメラです。)
###アプローチ1
def getdata3(originalImg: Image, materialImg: Image, transparentColor: str):
h = transparentColor.lstrip('#')
transRGB = tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
width, height = materialImg.size
imgdata = materialImg.getdata()
for i in range(height * width):
x = i % width
y = int(i / width)
pixdata = imgdata[i]
if pixdata == transRGB:
continue
originalImg.putpixel((x, y), pixdata)
originalImg.show()
def highCostChromaKey():
original = cv2.imread(
"original.png")
orImg = Image.fromarray(cv2.cvtColor(original, cv2.COLOR_BGR2RGB))
material = cv2.imread(
"transparent_1920x1020_FF0000.png")
mrImg = Image.fromarray(cv2.cvtColor(material, cv2.COLOR_BGR2RGB))
# stratTime = time.time()
getdata3(orImg, mrImg, "#FF0000")
# print(time.time() - stratTime)
[参考]
- https://kuranabe.hatenablog.com/entry/2018/08/18/234355 (getdata3の大部分を引用、一部改変)
-
https://stackoverflow.com/questions/29643352/converting-hex-to-rgb-value-in-python (getdata3の一行目、二行目。一部引用、改変)
オリジナルというものが貼り付け先、マテリアルが貼り付けるものです。
マテリアルのパスの最後にFF0000と書いてあると思うのですが、これは透過する色を示しています。
合成の手法としては、マテリアルの全ピクセルにアクセスして、FF0000ではない色だったらオリジナルの同じ位置に書き込もう。というもので、1920x1080の画像でテストしているのですが、すごく時間がかかります。一枚加工するだけならこのゴリ押し手法でも良いのですが、複数枚となると、現実的ではない時間がかかってしまいます。
私の実現したいことは時間に敏感なので違う方法を考えなければなりませんでした。
そこでマスク合成というものを試しました。
時間がないので、動くコードだけ載せます。
def mixWithMask():
# オリジナルと、色付きマスクを読み込む
start_time = time.perf_counter()
original = cv2.imread("original.png")
colorMask = cv2.imread(
"mask_text_in_box.png")
# 色付きマスクをモノクロマスクに変換。
bgrLower = np.array([0, 0, 255]) # 抽出する色の下限(BGR)
bgrUpper = np.array([0, 0, 255]) # 抽出する色の上限(BGR)
MonoMask = cv2.inRange(colorMask, bgrLower, bgrUpper)
MonoMaskBW = cv2.bitwise_not(MonoMask)
cv2.imwrite("./resources/color2mono_mask.png", MonoMask)
cv2.imwrite("./resources/color2mono_maskBW.png", MonoMaskBW)
mixed = cv2.bitwise_and(colorMask, colorMask, mask=MonoMaskBW)
cv2.imwrite("./resources/mixed.png", mixed)
orImg = Image.open("thumb-1920-1003880.png").convert("RGBA")
mrImg = Image.open("./resourcesmixed.png").convert("RGBA")
msImg = Image.open("./resources/color2mono_mask.png").convert("L")
im_2 = Image.new(mode=orImg.mode, size=mrImg.size, color=(0, 0, 0))
im = Image.composite(orImg, mrImg, msImg)
print("perf_counter = {:.7f}".format(time.perf_counter() - start_time))
im.show()
[参考]