python/OpenCVで透過pngをオーバレイする
昨日のリアルタイムな笑い男を実装するために使っていた画像の合成っていうかオーバレイっていうか上書きっていうか、とにかく笑い男をかぶせる奴。ググってもなかなかそれっぽい情報が出てこないので記録。
レナさんの画像に適当に書いた星マークを乗っけます。
とりあえず透過とか考えずに乗っけるだけ乗っけたバージョン。
import cv2
src = cv2.imread('star.png') # 乗っけたい画像。星。
dst = cv2.imread('lena.jpg') # 下敷きになる画像。レナさん。
width, height = src.shape[:2] # サイズを取得しておく。
# dst[上のy座標:下のy座標, 左のx座標:右のx座標]
dst[0:height, 0:width] = src
cv2.imwrite('out.jpg', dst)
凄くシンプル。
結果はこんな感じ。
で、アルファチャンネルを考慮して乗っけるバージョン。
import cv2
src = cv2.imread('star.png', -1) # -1を付けることでアルファチャンネルも読んでくれるらしい。
dst = cv2.imread('lena.jpg')
width, height = src.shape[:2]
mask = src[:,:,3] # アルファチャンネルだけ抜き出す。
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) # 3色分に増やす。
mask = mask / 255 # 0-255だと使い勝手が悪いので、0.0-1.0に変更。
src = src[:,:,:3] # アルファチャンネルは取り出しちゃったのでもういらない。
dst[0:height:, 0:width] *= 1 - mask # 透過率に応じて元の画像を暗くする。
dst[0:height:, 0:width] += src * mask # 貼り付ける方の画像に透過率をかけて加算。
cv2.imwrite('out.jpg', dst)
ちょっと長くなった。
結果はこんな。
追記
最新の環境(Python 3.8 / OpenCV 4.2)でも動くようにプログラムを更新しました。