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

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

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

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

OpenCV

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

Python 3.x

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

Q&A

解決済

1回答

9743閲覧

[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日にリリースされました。

0グッド

0クリップ

投稿2020/10/28 19:00

やりたいこと

以下の画像があります。
イメージ説明
これは事前の元画像を二値化したものでありますが、ここに写っている白黒画像について、pythonのopencvを用いて白色→赤色に黒色→青色になどと自由に色を変換したいと考えています。

以下、元のソースコードです。

import cv2 import numpy as np import matplotlib.pyplot as plt # (coins.png)の読み込み img = cv2.imread('tmp/coins.png') # グレースケールに変換する gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # Otuの二値化(入力はgrayのみ) ret, bin_img = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) # 輪郭の抽出 contours, _ = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 小さい輪郭は誤検出として削除 # 輪郭内部を塗りつぶすdrawContours draw = cv2.drawContours(bin_img, contours, -1, color=255,thickness=-1) print(draw.shape) print(draw) (246, 300) [[255 0 0 ... 0 0 0] [255 0 0 ... 0 0 0] [255 0 0 ... 0 0 0] ... [255 0 0 ... 0 0 0] [255 0 0 ... 0 0 0] [255 0 0 ... 0 0 0]]

試したこと

以下のようにnp.whereなどで特定の画素をいじれないか見てみましたが、そもそもrgbの色情報などがないため、特定の色に変換することができない??

draw = np.where(draw[:,0] >= 255, 255, 100)

最後に

どうか白黒rgbではない画像を白→赤、黒→青のように特定の色に変換する方法をアドバイスしてくれると助かります。

どうかよろしくお願いします。

オリジナル画像の出どころ

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

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

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

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

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

1T2R3M4

2020/10/28 23:31

GRAY2BGRで白黒RGBにするのは禁じ手なんですか。
oinari03

2020/10/29 00:56

いえ、そんなことないです。 できるのであればどんな手法でも大丈夫です。
fana

2020/10/29 02:32 編集

特に何も考えなければ「結果用の画像バッファを用意して,自前で全画素走査(ループ)して結果画像の画素値を決めていく」ことを素直に行えば済む,という話になりそうですが, 「そういう自明すぎる話をしたいのではなくて,なんつーか,こう,労せず一発で(?)やれるような方法は無いか?」といったような趣旨なのであれば,そのような話だということがもう少しわかりやすいように書かれるとよいのではないかな,とか思います. (「当然こう書けばやれるけども長いしめんどいじゃん? もっと簡単な方法を教えてみせてみろよ」みたいな)
1T2R3M4

2020/10/29 02:04 編集

例えばprint(draw)の下に以下7行を追加する感じでもいいんですかね。 w_mask = cv2.cvtColor(draw,cv2.COLOR_GRAY2BGR) r_img = img.copy() t_img = img.copy() r_img[:] = (0,0,255) t_img = w_mask & r_img cv2.imshow('masked',t_img) cv2.waitKey(-1) (白が赤になります。)
fana

2020/10/29 02:41

・3chの結果画像バッファを全面青色で用意する ・白黒画像をマスクとして用いて結果画像バッファの一部を赤に変える みたいな手順でよいのではないかと思うけど,それをpythonでどう書くのかは知らない.
guest

回答1

0

ベストアンサー

python

1np.where(2値画像[..., np.newaxis] == 255, 255に割り当てる色, 0に割り当てる色)

でできると思います。
[..., np.newaxis] は2値画像の形状は (H, W) なのに対し、カラー画像の形状は (H, W, C) なので、2値画像の形状を (H, W, 1) とすることで numpy のブロードキャストが効くようにする意図です。

python

1import cv2 2import numpy as np 3import matplotlib.pyplot as plt 4 5# (coins.png)の読み込み 6img = cv2.imread("sample.png") 7 8 9# グレースケールに変換する 10gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 11 12# Otuの二値化(入力はgrayのみ) 13ret, bin_img = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) 14 15 16# 輪郭の抽出 17contours, _ = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 18# 小さい輪郭は誤検出として削除 19 20# 輪郭内部を塗りつぶすdrawContours 21cv2.drawContours(bin_img, contours, -1, color=255, thickness=-1) 22 23 24color_fg = (255, 0, 0) # 2値画像で画素値255に割り当てる色 25color_bg = (0, 255, 0) # 2値画像で画素値0に割り当てる色 26dst = np.where(bin_img[..., np.newaxis] == 255, color_fg, color_bg).astype(np.uint8) 27cv2.imshow("dst", dst) 28cv2.waitKey(0) 29cv2.destroyAllWindows() 30

イメージ説明

投稿2020/10/29 03:56

編集2020/10/29 12:25
tiitoi

総合スコア21956

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

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

oinari03

2020/10/29 09:02

すみません。上記のコードをcv2.imshowで実行したところ以下のエラーが発生しました。どのような理由でしょうか? error ``` error Traceback (most recent call last) <ipython-input-19-4f392005acbf> in <module> 26 color_bg = (0, 255, 0) # 2値画像で画素値0に割り当てる色 27 dst = np.where(bin_img[..., np.newaxis] == 255, color_fg, color_bg) ---> 28 cv2.imshow('dst',dst) 29 cv2.waitKey(0) 30 cv2.destroyAllWindows() error: OpenCV(4.1.1) C:/projects/opencv-python/opencv/modules/highgui/src/precomp.hpp:131: error: (-215:Assertion failed) src_depth != CV_16F && src_depth != CV_32S in function 'convertToShow' ``` ソースコード全文 ``` import cv2 import numpy as np import matplotlib.pyplot as plt # (coins.png)の読み込み img = cv2.imread('tmp/coins.png') # グレースケールに変換する gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # Otuの二値化(入力はgrayのみ) ret, bin_img = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) # 輪郭の抽出 contours, _ = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 小さい輪郭は誤検出として削除 # 輪郭内部を塗りつぶすdrawContours cv2.drawContours(bin_img, contours, -1, color=255,thickness=-1) dst = np.empty_like(img) color_fg = (255, 0, 0) # 2値画像で画素値255に割り当てる色 color_bg = (0, 255, 0) # 2値画像で画素値0に割り当てる色 dst = np.where(bin_img[..., np.newaxis] == 255, color_fg, color_bg) cv2.imshow('dst',dst) cv2.waitKey(0) cv2.destroyAllWindows() ``` どうかよろしくお願いします。
tiitoi

2020/10/29 12:26

すいません。コードに誤りがあったので修正しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問