質問: cv2.findContours( binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) # すべての輪郭を描画 cv2.drawContours(img, contours, -1, color=(0, 255, 0), thickness=2) # 保存する。 cv2.imwrite(r"C:\Users\hirayama\Desktop\python_test\save_Python.png", img) # 表示 cv2.imshow("img", img) cv2.waitKey(0) cv2.imshow("img", mask) cv2.waitKey(0) ``` ### 実行結果 ![![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/aadb93e180dfeddd5ca87b4a8d86942b.png)](79400b0699ad908168425ad50bd64e42.png) ### 自分の考え 上記のコードは、ほとんど参考にさせていただいているので自分で書いたとは言えないのですが、とりあえず、すべての輪郭を抽出するのにグレースケール化し、二値化してから、drawContoursを行っています。 もしかしたら、これらの処理は背景透過にはいらないのかも? そのご透明化するにはアルファチャンネルをいじらなければならないみたいなのですが、輪郭抽出した外側を配列で選択しなければならないのかなと思っています。 ### 解決したいこと まずは、輪郭の外側を透明化できるコードを教えてほしいです。 また、これらの内容をふまえて、コードのレビューをお願いします。 よろしくお願いします!!
回答: まず `cv2.cvtColor(img, cv2.COLOR_RGB2RGBA)` で画像にアルファチャンネルを追加します。 次に背景は色が白 (255, 255, 255) なので、白の画素のアルファチャンネルの値を0にして透明にします。 コードにすると以下のようになります。 ``` import cv2 img = cv2.imread("sample.png") # RGBA に変換する。 rgba = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA) # 白 (背景) のアルファチャンネルは0にして、透明にする。 rgba..., 3] = np.where(np.all(img == 255, axis=-1), 0, 255) # 保存する。 cv2.imwrite("result.png", rgba) ``` 追記 ``` import cv2 import numpy as np # 画像を読み込む。 img = cv2.imread("sample.png") # グレースケールに変換する。 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 2値化する。 thresh, binary = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV) # 輪郭を抽出する。 contours, hierarchy = cv2.findContours( binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) # マスクを作成する。 mask = np.zeros_like(binary) # 輪郭内部 (透明化しない画素) を255で塗りつぶす。 cv2.drawContours(mask, contours, -1, color=255, thickness=-1) # RGBA に変換する。 rgba = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA) # マスクをアルファチャンネルに設定する。 rgba[..., 3] = mask # 保存する。 cv2.imwrite(r"result.png", rgba) ``` ![イメージ説明