OpenCVで透明画像の重ね合わせ
今回やること
左の”background.png”画像に透明チャンネル付き”penguin.png”画像を貼り付けて下のような画像を作る。
サンプルコード
# -*- coding: utf-8 -*-
import cv2
import numpy as np
def clip_alpha_image(x,y):
#x,yで貼り付け位置を選択
f_h, f_w, _ = foreground.shape
#透明部分が0、不透明部分が1のマスクを作る
alpha_mask = np.ones((f_h, f_w)) - np.clip(cv2.split(foreground)[3],0,1)
#貼り付ける位置の背景部分
target_background = background[y:y+f_h,x:x+f_w]
#各BRGチャンネルにalpha_maskを掛けて、前景の不透明部分が[0, 0, 0]のnew_backgroundを作る
new_background = cv2.merge(list(map(lambda x:x * alpha_mask,cv2.split(target_background))))
#BGRAをBGRに変換した画像とnew_backgroundを足すと合成できる
background[y:y + f_h,x:x+f_w] = cv2.merge(cv2.split(foreground)[:3]) + new_background
background = cv2.imread("background.png")
foreground = cv2.imread("penguin.png", -1)
clip_alpha_image(600, 250)
cv2.imwrite("result.png", background)
関数の説明
np.clip(array, min, max)
np.clipはarrayの値でminより小さい値はminにmaxより大きな値はmaxに変換したarrayを返します。
BGR = cv2.split(img)
cv2.splitはimgをチャンネル分解をする関数です。imgがBGR(青緑赤)画像のときBGR[0]は青チャンネル、BGR[1]は緑チャンネル、BGR[2]は赤チャンネルとなるようなリストを返します。RBGでは無くBGRとなるところは注意が必要です。
img = cv2.merge(BGR)
cv2.mergeはcv2.splitの逆の処理を行う関数です。