今でもちょいちょい見られている投稿のようなので、少々更新します。
以下のリポジトリで画像重ね合わせ用のクラスを公開しています。
元投稿の処理では全範囲の貼り付けを行っており処理が重いため、
該当部分のコピーのみに処理を変更しています。
当時の投稿は以下に残しています。
もはや、タイトルが詐欺くさい気がしないでもないです(第2弾
OpenCV単体だと、ちょっとだけ面倒なのでPillow(PIL)を利用しております。
画像に透過付き画像を重ねたいことが、ちょいちょいあるのですが、 パッと思いつく範囲で以下のような対応があります(大変な順に。。。
・αチャンネルを元にマスク画像を生成し、マスク画像で切り抜いた画像を重ねる
・Pillow等の他ライブラリを用いて画像を重ねる
今回はパッと表示したいだけだったので、Pillowを利用します。 ソースコードは以下。
#!/usr/bin/env python # -*- coding: utf-8 -*- import cv2 as cv import numpy as np from PIL import Image class CvOverlayImage(object): """ [summary] OpenCV形式の画像に指定画像を重ねる """ def __init__(self): pass @classmethod def overlay( cls, cv_background_image, cv_overlay_image, point, ): """ [summary] OpenCV形式の画像に指定画像を重ねる Parameters ---------- cv_background_image : [OpenCV Image] cv_overlay_image : [OpenCV Image] point : [(x, y)] Returns : [OpenCV Image] """ overlay_height, overlay_width = cv_overlay_image.shape[:2] # OpenCV形式の画像をPIL形式に変換(α値含む) # 背景画像 cv_rgb_bg_image = cv.cvtColor(cv_background_image, cv.COLOR_BGR2RGB) pil_rgb_bg_image = Image.fromarray(cv_rgb_bg_image) pil_rgba_bg_image = pil_rgb_bg_image.convert('RGBA') # オーバーレイ画像 cv_rgb_ol_image = cv.cvtColor(cv_overlay_image, cv.COLOR_BGRA2RGBA) pil_rgb_ol_image = Image.fromarray(cv_rgb_ol_image) pil_rgba_ol_image = pil_rgb_ol_image.convert('RGBA') # composite()は同サイズ画像同士が必須のため、合成用画像を用意 pil_rgba_bg_temp = Image.new('RGBA', pil_rgba_bg_image.size, (255, 255, 255, 0)) # 座標を指定し重ね合わせる pil_rgba_bg_temp.paste(pil_rgba_ol_image, point, pil_rgba_ol_image) result_image = \ Image.alpha_composite(pil_rgba_bg_image, pil_rgba_bg_temp) # OpenCV形式画像へ変換 cv_bgr_result_image = cv.cvtColor( np.asarray(result_image), cv.COLOR_RGBA2BGRA) return cv_bgr_result_image
使用例は以下。 例では、いらすとや様の画像を使用しております。
if __name__ == '__main__': cv_background_image = cv.imread("bg_takeyabu_layer2.jpg") cv_overlay_image = cv.imread( "ninja_hashiru.png", cv.IMREAD_UNCHANGED) # IMREAD_UNCHANGEDを指定しα込みで読み込む cv_overlay_image = cv.resize(cv_overlay_image, (100, 100)) point = (550, 250) image = CvOverlayImage.overlay(cv_background_image, cv_overlay_image, point) cv.imshow("sample", image) cv.waitKey(0)
+ ⇒
以上。