Python2つの画像を重ね合わせる

python コンピュータ
python
#!/usr/bin/env python3
# coding: utf8

# 2つの画像を重ね合わせる

import cv2
import numpy as np

# 画像ファイルを読み込む(32bitRGBA)
im = cv2.imread('rgba.png', cv2.IMREAD_UNCHANGED)

# 画像ファイルを読み込む(32bitRGBA)
im2 = cv2.imread('rgba2.png', cv2.IMREAD_UNCHANGED)

# 重ね合わせ

rgb = im[:,:,:3]
a = im[:,:,3:]

rgb2 = im2[:,:,:3]
a2 = im2[:,:,3:]

dst = rgb * (a/255) + rgb2 * (a2/255)

# 結果を保存
cv2.imwrite('logo_dst.png', dst)

結果

アルファチャンネルの値が0(透明)と255(不透明)だったので、255で割り、RGBに掛けることで不透明はそのままで、透明部分が0になります。両画像ファイルに同様の計算を施し、加算することで互いの透明部分(0)が補完されるようになります。

 
これだけだとアルファチャンネルを削除しても同じ結果になるので、少し色をいじってみます。

#!/usr/bin/env python3
# coding: utf8

# 2つの画像を重ね合わせる

import cv2
import numpy as np

# 画像ファイルを読み込む(32bitRGBA)
im = cv2.imread('rgba.png', cv2.IMREAD_UNCHANGED)

# 画像ファイルを読み込む(32bitRGBA)
im2 = cv2.imread('rgba2.png', cv2.IMREAD_UNCHANGED)

# 重ね合わせ

rgb = im[:,:,:3]
rgb = np.where(rgb == 0, 127, rgb) # 灰色
a = im[:,:,3:]

rgb2 = im2[:,:,:3]
rgb2[:,:,(0,1)] = np.where(rgb2[:,:,(0,1)] == 0, 200, rgb2[:,:,(0,1)]) # 水色
a2 = im2[:,:,3:]

dst = rgb * (a/255) + rgb2 * (a2/255)

# 結果を保存
cv2.imwrite('logo_dst.png', dst)

結果:

色を変えることで輪郭部分が縁取りの様になりました。

OpenCVのライブラリも強力なのですが、Numpyで配列に対し演算を簡潔に記述できる点が素晴らしいです。

Numpyなどのライブラリが無い場合ピクセル単位にアクセスして演算を施すわけですが、基本的にメモリの走査をすることになります。
そういった処理では、コンピュータよりのコードを生成できるC言語などで作成すると高速に処理できますが、スクリプト言語や中間コードで実行するタイプのプログラミング言語では実用的な速度を担保するのが難しいジャンルになります。
その点スクリプト言語でありながら高速な処理を担保しつつ完結に記述できるNumpyが使えるPythonが画像加工でよく使われる理由ではないかと考えます。

個人的にはC#とかでも使えるとよいのですが…

コメント