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

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

新規登録して質問してみよう
ただいま回答率
85.31%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

711閲覧

OpenCVを使った画像処理での疑問が解消できません

Kasairyu

総合スコア12

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/12/16 11:57

前提

OpenCVを使った画像処理での疑問が解消できません。

実現したいこと

  • 画像内の特定の色以外を暗くする

発生している問題・エラーメッセージ

下のコードを実行するとプライマルウィンドウのスクリーンショットを撮って赤青緑の内、指定した色以外を薄暗くした画像が描画されます。
私が気にしているのは11行目の記述です。

hsv_img_ori =cv2.cvtColor(frame,cv2.COLOR_RGB2HSV)

frameはBGR画像であり、この画像に対してRGBをHSVに変換するcv2.cvtColor(frame,cv2.COLOR_RGB2HSV)は明らかに正常な動作をしないと思います。
しかし、この記述をcv2.cvtColor(frame,cv2.COLOR_BGR2HSV)と直すと38行目の時点でdstはscolor ="red"の場合青の領域を、scolor ="blue"の場合赤の領域をマスクしてしまいます。
13行目の時点でhsv_img_oriとhsv_imgをcv2.imshow('hsv_img_ori', hsv_img_ori)で確認したところ外見上はどちらも全く一緒で、何故この処理で成立するのか理解できません。どなたかご解説ください。

該当のソースコード

Python

1from PIL import Image, ImageTk, ImageOps # 画像データ用 2from PIL import ImageGrab 3import numpy as np 4import cv2 5 6img = ImageGrab.grab() 7capture = np.array(img, dtype=np.uint8) 8frame = capture 9 10cv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 11hsv_img_ori =cv2.cvtColor(frame,cv2.COLOR_RGB2HSV) 12hsv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 13 14bg_saturation = 4 15# 背景の明るさ 16bg_value = 0.2 17s_magnification = bg_saturation # 彩度(Saturation)の倍率 18v_magnification = bg_value # 明度(Value)の倍率 19hsv_img[:,:,(1)] = hsv_img[:,:,(1)]*s_magnification # 彩度の計算 20hsv_img[:,:,(2)] = hsv_img[:,:,(2)]*v_magnification # 明度の計算 21img_bgr = cv2.cvtColor(hsv_img,cv2.COLOR_HSV2RGB) 22 23hsv_s = 10 24hsv_v = 10 25# 三原色抽出 26red_mask = cv2.inRange(hsv_img_ori, (0, hsv_s,hsv_v), (20,255,255))+cv2.inRange(hsv_img_ori, (150, hsv_s,hsv_v), (180,255,255)) 27blue_mask = cv2.inRange(hsv_img_ori, (80, hsv_s,hsv_v), (130,255,255)) 28green_mask = cv2.inRange(hsv_img_ori, (30, hsv_s,hsv_v), (80,255,255)) 29 30scolor ="red" 31 32if scolor =="red": 33 dst = cv2.bitwise_and(cv_img, cv_img, mask=red_mask) 34elif scolor =="green": 35 dst = cv2.bitwise_and(cv_img, cv_img, mask=green_mask) 36elif scolor =="blue": 37 dst = cv2.bitwise_and(cv_img, cv_img, mask=blue_mask) 38 39# 合成・型抜き 40rows,cols,channels = dst.shape 41roi = img_bgr[0:rows, 0:cols ] 42img2gray = cv2.cvtColor(dst,cv2.COLOR_RGB2GRAY) 43ret, mask = cv2.threshold(img2gray, 1, 255, cv2.THRESH_BINARY) 44mask_inv = cv2.bitwise_not(mask) 45img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv) 46img2_fg = cv2.bitwise_and(dst,dst,mask = mask) 47 48dst = cv2.add(img1_bg,img2_fg) 49dst = cv2.cvtColor(dst, cv2.COLOR_RGB2BGR) 50img_bgr[0:rows, 0:cols ] = dst 51# NumPyのndarrayからPillowのImageへ変換 52pil_image = Image.fromarray(img_bgr) 53pil_image.show() 54

試したこと

cv2.cvtColor(dst, cv2.COLOR_RGB2BGR)等で色々変えてみましたが色がおかしくなる一方で特に成果は無し。
cv2.imshow()で見る限り、11行に問題がある様にしか見えない。

補足情報(FW/ツールのバージョンなど)

言語:Python
ツール:VScode

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

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

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

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

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

bsdfan

2022/12/17 06:57

ImageGrab.grab() の戻り値について確認してみてはどうでしょう。BGR ではなく RGB で返ってきているということでは?
Kasairyu

2022/12/17 07:08

確かにImageGrab.grab()の段階で画像はRGBでした。しかし、capture = np.array(img, dtype=np.uint8)を通すことでBGRになっています。
bsdfan

2022/12/17 07:40

> capture = np.array(img, dtype=np.uint8)を通すことでBGRになっています。 そんなことは起きないと思うのですが、どうやって確認しましたか?
Kasairyu

2022/12/17 08:06 編集

配列はprint(img.mode)では確認できなかったのでcv2.imshow('capture', capture)で視覚的に確認しました。
bsdfan

2022/12/17 08:45

opencvはBGRを期待しているので、cv2.imshow() で色が正しく表示されればBGR、おかしければRGBのデータです。Rだけの画像、Bだけの画像などで試してみて、print(capture) してみるのが確実です。
Kasairyu

2022/12/17 08:56

pil_image = Image.fromarray()とpil_image.show()で途中途中の画像をで確認したらRGBの画像のままでした。大変失礼いたしました。その上でframeはRGB画像であるという前提の下修正するとcv_imgは色変換の必要が無く、この処理の所為で色々狂っていることが理解できました。 今まで二重に間違えて正解になっていた部分が理解できる形になり解決しました。ありがとうございます。
guest

回答1

0

自己解決

前提の認識と色変換を多重に間違えた結果何故か正しい結果が得られていました。正しくは以下の通りでした。

Python

1from PIL import Image, ImageTk, ImageOps # 画像データ用 2from PIL import ImageGrab 3import numpy as np 4import cv2 5 6img = ImageGrab.grab() 7capture = np.array(img, dtype=np.uint8) 8frame = capture 9pil_image = Image.fromarray(frame) 10 11cv_img = frame 12hsv_img_ori =cv2.cvtColor(frame,cv2.COLOR_RGB2HSV) 13hsv_img = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV) 14 15bg_saturation = 1 16# 背景の明るさ 17bg_value = 0.2 18s_magnification = bg_saturation # 彩度(Saturation)の倍率 19v_magnification = bg_value # 明度(Value)の倍率 20hsv_img[:,:,(1)] = hsv_img[:,:,(1)]*s_magnification # 彩度の計算 21hsv_img[:,:,(2)] = hsv_img[:,:,(2)]*v_magnification # 明度の計算 22img_bgr = cv2.cvtColor(hsv_img,cv2.COLOR_HSV2RGB) 23 24hsv_s = 10 25hsv_v = 10 26# 三原色抽出 27red_mask = cv2.inRange(hsv_img_ori, (0, hsv_s,hsv_v), (20,255,255))+cv2.inRange(hsv_img_ori, (150, hsv_s,hsv_v), (180,255,255)) 28blue_mask = cv2.inRange(hsv_img_ori, (80, hsv_s,hsv_v), (130,255,255)) 29green_mask = cv2.inRange(hsv_img_ori, (30, hsv_s,hsv_v), (80,255,255)) 30 31scolor ="red" 32 33if scolor =="red": 34 dst = cv2.bitwise_and(cv_img, cv_img, mask=red_mask) 35elif scolor =="green": 36 dst = cv2.bitwise_and(cv_img, cv_img, mask=green_mask) 37elif scolor =="blue": 38 dst = cv2.bitwise_and(cv_img, cv_img, mask=blue_mask) 39 40# 合成・型抜き 41rows,cols,channels = dst.shape 42roi = img_bgr[0:rows, 0:cols ] 43img2gray = cv2.cvtColor(dst,cv2.COLOR_RGB2GRAY) 44ret, mask = cv2.threshold(img2gray, 1, 255, cv2.THRESH_BINARY) 45mask_inv = cv2.bitwise_not(mask) 46img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv) 47img2_fg = cv2.bitwise_and(dst,dst,mask = mask) 48 49dst = cv2.add(img1_bg,img2_fg) 50img_bgr[0:rows, 0:cols ] = dst 51# NumPyのndarrayからPillowのImageへ変換 52pil_image = Image.fromarray(img_bgr) 53pil_image.show(title="END")

投稿2022/12/17 08:59

Kasairyu

総合スコア12

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問