【OpenCV】【Python】画像上に透過付き画像を重ねて描画

今でもちょいちょい見られている投稿のようなので、少々更新します。

以下のリポジトリで画像重ね合わせ用のクラスを公開しています。
元投稿の処理では全範囲の貼り付けを行っており処理が重いため、
該当部分のコピーのみに処理を変更しています。
<a href="https://github.com/Kazuhito00/cvoverlayimg"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/Kazuhito00/cvoverlayimg.png" width="460px"></a>

当時の投稿は以下に残しています。

---

もはや、タイトルが詐欺くさい気がしないでもないです（第2弾
⇒第1弾：[【OpenCV】【Python】画像上に日本語のテキストを描画](https://qiita.com/Kazuhito/items/6a030b3746d941c3d9c7 "【OpenCV】【Python】画像上に日本語のテキストを描画")
OpenCV単体だと、ちょっとだけ面倒なのでPillow(PIL)を利用しております。

画像に透過付き画像を重ねたいことが、ちょいちょいあるのですが、
パッと思いつく範囲で以下のような対応があります（大変な順に。。。
　・αチャンネルを元にマスク画像を生成し、マスク画像で切り抜いた画像を重ねる
　・Pillow等の他ライブラリを用いて画像を重ねる

今回はパッと表示したいだけだったので、Pillowを利用します。
ソースコードは以下。

```python:CvOverlayImage.py
#!/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
```

使用例は以下。
例では、いらすとや様の画像を使用しております。

```python
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)
```
<img src="https://qiita-image-store.s3.amazonaws.com/0/140207/fbba3951-f02e-d9d2-4416-f7c162d31dcd.jpeg" width="30%">　＋　<img src="https://qiita-image-store.s3.amazonaws.com/0/140207/c915b5f4-71b0-06e7-93d6-0035f54ec5cf.png" width="20%">
⇒　<img src="https://qiita-image-store.s3.amazonaws.com/0/140207/36935249-8f77-98fa-2bfc-704919a465c9.png" width="80%">

以上。