【python】アルファ値をもつ画像から透明属性を除いて処理できるようにした【opencv】

透過画像にputtextするとバグる!!!!

色がおかしい、変な色になる、なんでじゃ!!

4チャンネルの確認

透明な画像の情報を持っている画像は色情報で4つの情報を持っている

ようするにピクセル

位置x座標、y座標の2つと色情報のBlue,Green,Red,Alphaと4つの情報がある

たとえば切り抜きがひどいが透過画像のつぎのねこ

f:id:majimanjipien:20210315193523p:plain

これの形はshapeでわかるので出力してみる

img = cv2.imread("./test.png",-1)
print(img.shape)

とすれば

(336, 378, 4)

となってたしかに4チャンネルになっている。

問題点とその結果

問題のプログラム

cv2.puttextを実行しようとした。

import cv2
img = cv2.imread("./test.png",-1)
h,w = img.shape[0],img.shape[1]#文字の配置場所決めのため、とくに今回不要だけどまあかいてみた
cv2.putText(img, 'A', (int(w/2), int(h/2)), cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 255), 5, cv2.LINE_AA)#赤文字
cv2.imwrite('result.png', img)

問題の結果

result.png

f:id:majimanjipien:20210315200450p:plain

何故か挙動がおかしい、(0, 0, 255) で赤を指定しているのに色がおかしいとか

解決点とその結果

opencvのリファレンスを見よう

描画関数 — opencv 2.2 documentation

ここをみると

これらの関数は,アルファ透過をサポートしません.目的画像が4チャンネルである場合でも color[3] には,単なるピクセル値がコピーされるだけです.したがって,もし半透明な形状を描画したい場合は,それを別のバッファに描画してから画像とブレンドするとよいでしょう.

まじか!

解決したプログラム

import cv2
import copy

img = cv2.imread("./test.png",-1)
img_3channel = copy.deepcopy(img[:,:,:3]) #3チャンネル分の抜き出し
h,w = img.shape[0],img.shape[1]#文字の配置場所決めのため、とくに今回不要
cv2.putText(img_3channel, 'A', (int(w/2), int(h/2)), cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 255), 5, cv2.LINE_AA)
img[:,:,:3] = img_3channel[:,:,:3]#アルファ値以外を加工画像から戻す
cv2.imwrite('result.png', img)

解決した結果

4チャンネルの画像をかこうしてかつ透過情報ももったimgができあがりました

result.png

f:id:majimanjipien:20210315200304p:plain

アルファ値を削ることなく opencvのputtext関数を用いたい場合は3チャンネルにもどしてからやるとよかったりした