質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

PyCharm

エディター・開発ツール

Q&A

解決済

1回答

9287閲覧

OpenCVを使って初めての背景透過

oinari03

総合スコア59

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

PyCharm

エディター・開発ツール

0グッド

1クリップ

投稿2019/10/31 14:12

やりたいこと

ある画像の輪郭を抽出してその背景だけを透明化して中身を抜き出したいです!!!

実際に書いたコード

python

1import cv2 2 3# 画像を読み込む。 4# -1をつけることでアルファチャンネルもよんでくれるらしい 5img = cv2.imread(r"C:\Users\hirayama\Desktop\python_test\Python.png", -1) 6# アルファチャンネルだけ抜き出す 7mask = img[:, :, 3] 8# 0~255まであって0が透明らしい 9mask = 0 10# グレースケールに変換する。 11gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 12 13# 2値化する。 14thresh, binary = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV) 15 16# 輪郭を抽出する。 17contours, hierarchy = cv2.findContours( 18 binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE 19) 20 21# すべての輪郭を描画 22cv2.drawContours(img, contours, -1, color=(0, 255, 0), thickness=2) 23 24# 保存する。 25cv2.imwrite(r"C:\Users\hirayama\Desktop\python_test\save_Python.png", img) 26 27# 表示 28cv2.imshow("img", img) 29cv2.waitKey(0) 30 31cv2.imshow("img", mask) 32cv2.waitKey(0)

実行結果

イメージ説明

自分の考え

上記のコードは、ほとんど参考にさせていただいているので自分で書いたとは言えないのですが、とりあえず、すべての輪郭を抽出するのにグレースケール化し、二値化してから、drawContoursを行っています。
もしかしたら、これらの処理は背景透過にはいらないのかも?

そのご透明化するにはアルファチャンネルをいじらなければならないみたいなのですが、輪郭抽出した外側を配列で選択しなければならないのかなと思っています。

解決したいこと

まずは、輪郭の外側を透明化できるコードを教えてほしいです。
また、これらの内容をふまえて、コードのレビューをお願いします。

よろしくお願いします!!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2019/10/31 17:14

背景の白だけを透明にするという回答でもいいですか?
oinari03

2019/10/31 23:08

それでも大丈夫です!!
guest

回答1

0

ベストアンサー

まず cv2.cvtColor(img, cv2.COLOR_RGB2RGBA) で画像にアルファチャンネルを追加します。
次に背景は色が白 (255, 255, 255) なので、白の画素のアルファチャンネルの値を0にして透明にします。

コードにすると以下のようになります。

python

1import cv2 2 3img = cv2.imread("sample.png") 4 5# RGBA に変換する。 6rgba = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA) 7 8# 白 (背景) のアルファチャンネルは0にして、透明にする。 9rgba[..., 3] = np.where(np.all(img == 255, axis=-1), 0, 255) 10 11# 保存する。 12cv2.imwrite("result.png", rgba)

追記

python

1import cv2 2import numpy as np 3 4# 画像を読み込む。 5img = cv2.imread("sample.png") 6 7# グレースケールに変換する。 8gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 9 10# 2値化する。 11thresh, binary = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV) 12 13# 輪郭を抽出する。 14contours, hierarchy = cv2.findContours( 15 binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE 16) 17 18# マスクを作成する。 19mask = np.zeros_like(binary) 20 21# 輪郭内部 (透明化しない画素) を255で塗りつぶす。 22cv2.drawContours(mask, contours, -1, color=255, thickness=-1) 23 24# RGBA に変換する。 25rgba = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA) 26 27# マスクをアルファチャンネルに設定する。 28rgba[..., 3] = mask 29 30# 保存する。 31cv2.imwrite(r"result.png", rgba)

イメージ説明

投稿2019/11/01 08:18

編集2019/11/01 09:58
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oinari03

2019/11/01 09:16

回答ありがとうございます!!質問なんですが、 これは、白の部分を透明化する方法であって、例えば、白い絵の画像であったらすべて透明になってしまうということですよね。
tiitoi

2019/11/01 09:36

> 例えば、白い絵の画像であったらすべて透明になってしまうということですよね。 そうなりますね。輪郭内部は透明にしない場合は追記のようにしてみてください。
oinari03

2019/11/01 09:44

また、グレースケールして、contoursのように輪郭抽出をする必要がないということですか?
tiitoi

2019/11/01 09:57 編集

輪郭内部は透明にしないのであれば、グレースケール→2値化→輪郭抽出が必要です。 回答に追記したコードではそうしています。
oinari03

2019/11/01 10:06

ありがとうございます! とても参考になりました!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問