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])
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 の逆の処理を行う関数です。
コメント