はじめに
PythonでOpenCVを使って2つの画像を合成(ブレンディング)する方法について紹介します。
画像の合成というと画像に透かしを付けたり、動画編集なのどで初めの画像がフェードアウトしながら次の画像がフェードインするようなディゾルブなどに応用できる手法です。少し難しい印象があるかもしれませんが、OpenCVを使って比較的簡単に実現することが出来ます。
画像の合成
2つの画像を合成はcv2.addWeighted
関数を使用します。
合成する画像は下の2つを用意しました。
合成した結果の画像は次のようになります。
cv2.addWeighted関数
cv2.addWeighted関数の構文
引数は7つですが、その中で必須のものは5つになります。
引数
名称 | 説明 |
画像データ1(必須) | 合成する1つ目の画像 |
alpha(必須) | 画像データ1の重み |
画像データ2(必須) | 合成する2つ目の画像 |
beta(必須) | 画像データ2の重み |
gamma(必須) | 足し合わされた値に加算されるスカラー値 |
dst(オプション) | 合成された出力画像データ。指定された場合、結果がこの変数に格納されます。指定されない場合は、新しい配列が作成されて結果が格納され戻り値として取得できます。 |
dtype(オプション) | 出力される画像データのデータ型。画像データ1と画像データ2のデータ型が同じ場合、 -1 に設定できます。 |
戻り値
合成された出力画像データ
引数のdtypeが指定されている場合は戻り値がそのデータ型になります。
使い方
cv2.addWeighted
関数ではそれぞれの画素値に対して、下に示すように2つの配列の加重合計を計算します。
dst = saturate(画像データ1 ∗ alpha + 画像データ2 ∗ beta + gamma)
このため、alpha, beta, gammaの値が大きすぎるとハレーション気味になってしまいます。
下のコードではalphaは0〜1の間となる"0.5"を取るように設定しています。alphaとbetaの合計が "1"になるように重みを調整することで、重み付けのバランスが取りやすくなります。
また、gammaの値は"0"としています。gammaは2つの入力画像の和に追加される定数です。明るさの調整として使用することができます。
import cv2 # 1つ目の画像の重みの値 alpha = 0.5 # 画像を読み込む src1 = cv2.imread('cat.webp') # 1つ目の画像 src2 = cv2.imread('duck.webp') # 2つ目の画像 # 画像を合成する beta = 1.0 - alpha # 2つ目の画像の重みの値, image = cv2.addWeighted(src1, alpha, src2, beta, 0.0) # 合成した画像を保存する cv2.imwrite('result.webp', image)
addWeighted
関数の注意点は次の通りです。
gammaの値を100に設定するとこの様に明るすぎる画像になってしまいます。
コードは次の通りです。
image = cv2.addWeighted(src1, alpha, src2, beta, 100.0)
応用例(1):画像のコントラスト調整
画像のコントラストを調整する例を示します。
白色の画像とコントラストを調整したい画像を合成することで調整を行います。
import cv2 import numpy as np # 画像を読み込む src = cv2.imread('duck.webp') # 白色画像を作成する white_img = np.zeros(src.shape, src.dtype) white_img.fill(255) # 画像のコントラストを調整する alpha = 2.5 # コントラストの係数 gamma = 50 # オフセット adjusted_img = cv2.addWeighted(src, alpha, white_img, 1 - alpha, gamma) # フィルタ処理された画像を保存する cv2.imwrite('adjusted_img.webp', adjusted_img)
応用例(2):平滑化フィルタ
重み付き平均による平滑化フィルタの適応例を示します。
入力画像に平滑化フィルタ処理を施した画像と入力画像を合成して重み付き平均による平滑化フィルタの適用例です。平滑化フィルタ処理を施しただけの画像とは少し異なる画像が得られます。
import cv2 import numpy as np # 画像を読み込む src = cv2.imread('duck.webp') # 平滑化フィルタを作成する kernel_size = 5 # カーネルサイズ kernel = np.ones((kernel_size, kernel_size), np.float32) / (kernel_size * kernel_size) smoothed_img = cv2.filter2D(src, -1, kernel) # フィルタ処理された画像を保存する cv2.imwrite('filter2D.webp', smoothed_img) # 重み付き平均によって、フィルタを適用する alpha = 0.3 # 元の画像の重み beta = 1 - alpha # フィルタの重み smoothed_img = cv2.addWeighted(img, alpha, cv2.filter2D(img, -1, kernel), beta, 0) # フィルタ処理された画像を保存する cv2.imwrite('smoothed_img.webp', smoothed_img)
左の画像が入力画像に平滑化フィルタ処理を施した画像で、右の画像が重み付き平均による平滑化フィルタを適用した画像となります。
上記コードのパラメータの場合、平滑化フィルタの影響がマイルドな画像が得られます。
おわりに
cv2.addWeighted
関数は2つの画像の合成を行う機能ですが、コントラストの調整、平滑化フィルタの適用などの応用例を紹介しました。使い方を工夫することで様々な応用ができることがわかりました。
最後までご覧頂きありがとうございました。
■(広告)OpenCVの参考書としてどうぞ!■
参考リンク
OpenCV: Operations on arrays
OpenCV: Adding (blending) two images using OpenCV