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

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

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

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

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

Q&A

解決済

1回答

2032閲覧

OpenCV 明るさの強弱に応じた輪郭検出がしたい

lime00

総合スコア25

OpenCV

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

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

0グッド

0クリップ

投稿2021/10/14 00:52

編集2021/10/14 04:57

現在,OpenCVをPythonで動かして画像処理を行なっています.
Canny法などの手法を利用し,"画像中の輪郭部分を検出して,その部分のみを白,その他の部分は黒となるような輪郭画像を作成する"などの処理はできるようになりました.
ただ,輪郭の明るさの強弱に応じて反応値の大小を変えるといった処理ができず,調べてみてもわからない状態です.
例えば,「輪郭部分のみを白くする輪郭画像を作る場合でも,対象部分の明るさの変化の強弱が大きいほど,より輝度値の高い白になる」などの処理はOpenCVでできるものなのでしょうか.
詳しい方,ご教授のほどよろしくお願いします.

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

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

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

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

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

jbpb0

2021/10/14 02:03

質問の「色の変化の強弱」を「明るさの変化の強弱」と解釈して、以下書きます 勘違いしてたら、スルーしてください https://pystyle.info/opencv-edge-detection/ http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_gradients/py_gradients.html あたりで紹介されてる微分フィルタの結果は、明るさの変化の強弱に応じた値です コード例はPythonですが、C++にも同じものがあります ただし、輪郭部分だけの結果ではありません 輪郭部分だけの結果は、上記のような微分フィルタの結果から、 > 画像中の輪郭部分を検出して,その部分のみを白 で検出された輪郭の画素の部分だけ取り出したらいいと思います なお、上記参考Webページの二つ目の方にも書いてありますが、微分して負になる数値の結果が消えてしまわないように、ご注意ください
lime00

2021/10/14 04:55

ありがとうございます. 確かに「明るさの変化の強弱」と表現するのが適切でした. ご指摘ありがとうございます.
guest

回答1

0

ベストアンサー

元の画像の輝度勾配に応じて,適当に結果画像の輝度を決定すればよいのではないでしょうか.


Sobelフィルタのようなエッジ検出フィルタの結果値から,輝度勾配の強度を見積もることができるでしょう.

例えば,良く見る 3x3 の Sobelフィルタ:

-1 0 1 -2 0 2 -1 0 1

-1 -2 -1 0 0 0 1 2 1

から求まる2つの結果値{SX,SY}から,
輝度勾配の強度 = sqrt( SX*SX + SY*SY )
とか何とかして見積ればよいでしょう.

あとはてきとーにその値の大小に応じた結果画像を描画するだけですね.


てきとーな例を追加(コードはC++ですが)

結果画像:上から{入力,Cannyの結果,Sobelから求めた強度に基づくてきとーな明暗描画結果}
イメージ説明

C++

1int main() 2{ 3 cv::Mat Src = cv::imread( "Kuro.png", cv::IMREAD_GRAYSCALE ); 4 if( Src.empty() )return 0; 5 //Sobel 6 cv::Mat SX( Src.size(), CV_16S ); 7 cv::Mat SY( Src.size(), CV_16S ); 8 cv::Sobel( Src, SX, CV_16S, 1, 0 ); 9 cv::Sobel( Src, SY, CV_16S, 0, 1 ); 10 //Canny 11 cv::Mat Mask; 12 cv::Canny( Src, Mask, 100, 50 ); 13 //ShowImgは単なる表示用 14 cv::Mat ShowImg; 15 cv::vconcat( Src, Mask, ShowImg ); 16 17 //Maskの内容をSobelの結果を用いて明暗がついた感じに更新 18 for( int y=0; y<Src.rows; ++y ) 19 { 20 unsigned char *pMask = Mask.ptr<unsigned char>(y); 21 const short *pSX = SX.ptr<short>(y); 22 const short *pSY = SY.ptr<short>(y); 23 for( int x=0; x<Src.cols; ++x, ++pMask, ++pSX, ++pSY ) 24 { 25 if( !*pMask )continue; 26 auto Mag = sqrt( (*pSX * *pSX) + (*pSY * *pSY) ); 27 *pMask = (unsigned char)( std::min(Mag, 255.0) ); 28 } 29 } 30 31 //結果表示 32 cv::vconcat( ShowImg, Mask, ShowImg ); 33 cv::imshow( "Result", ShowImg ); 34 if( cv::waitKey() == 's' ){ cv::imwrite( "Result.png", ShowImg ); } 35 return 0; 36}

投稿2021/10/14 01:34

編集2021/10/14 05:48
fana

総合スコア11658

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

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

fana

2021/10/14 01:43

…っていう話がよくわからん,という場合, 「OpenCV Sobel」とかで画像検索とかしてみればよいかもしれません. エッジ強度に応じた白黒具合の絵みたいなのを見つけることができるでしょう.
lime00

2021/10/14 04:46

詳しいご解説ありあがとうございます. 勉強になりました.
fana

2021/10/14 04:56

cartToPolar なんてのがあるので これにSobelの結果を与えれば,回答に書いた勾配強度の計算になる.(あと,追加で勾配方向も得られる).
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問