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

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

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

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

Python

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

Q&A

1回答

784閲覧

画像輪郭処理Python3

hikari.13

総合スコア7

OpenCV

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

Python

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

0グッド

0クリップ

投稿2021/07/25 06:08

編集2021/07/25 06:34

Python3を勉強している初学者になります。
現在、画像のA4用紙のみを囲いたいのですが、下記画像のような表示なってしまい
囲うことができないため、ご教示いただけると幸いです。

Python3

1import cv2 2import numpy as np 3 4 5img = cv2.imread("****",1) 6height = img.shape[0] 7width = img.shape[1] 8img = cv2.resize(img , (int(width*0.5), int(height*0.5))) 9 10# グレースケールに変換する。 11grray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 12 13# 2値化する 14ret, bin_img = cv2.threshold(grray, 155, 255, cv2.THRESH_BINARY) 15cv2.imshow("img",bin_img) 16 17# 輪郭を抽出する。 18contours, hierarchy = cv2.findContours( 19 bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE 20) 21 22 # 面積の大きいもののみ選別 23areas = [] 24for cnt in contours: 25 area = cv2.contourArea(cnt) 26 if area > 10000: 27 epsilon = 0.1*cv2.arcLength(cnt,True) 28 approx = cv2.approxPolyDP(cnt,epsilon,True) 29 areas.append(approx) 30 31 32# 小さい輪郭は誤検出として削除する 33#contours = list(filter(lambda x: cv2.contourArea(x) > 100, contours)) 34 35# 輪郭を描画する。 36cv2.drawContours(img,areas, -1, color=(0, 0, 255), thickness=3) 37#cv2.drawContours(img,contours,-1,(0,255,0),3) 38 39cv2.imshow("Image",img) 40cv2.waitKey(0) 41cv2.destroyAllWindows()

下記画像は出力した際に出た画像になります。
*元の画像には赤線はございません。
イメージ説明

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

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

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

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

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

ppaul

2021/07/25 06:19

元の画像に赤い線は入っているのですか? 入っていないなら、その画像を質問に追加した方がよいでしょう。
hikari.13

2021/07/25 06:34

失礼いたしました。 ありがとうございます。
guest

回答1

0

所望の結果データがどんな形なのかがわからないですが……

とりあえず質問に貼られた絵を見るに,A4用紙の一部(右上角)が2値化で切れてしまっているのが良くない点なのかな? とか思ったので,
右側の絵を adaptiveThreshold に食わせたらどうなるかやってみました.

下図左側の絵(これは,質問に貼られた絵の右側の部分を適当に手作業で切り出して,1/4程度に縮小したもの)を adaptiveThreshold に食わせた結果が下図の中央です.

この画像例だと,床の光っている部分がA4の領域にくっついてくるので,
なんとなくモルフォロジに食わせた結果が図の右側です.
(まぁ,この後処理はこの画像に特化した話になってしまうので,実用的な話にはなり得ない可能性が高いです)
様々な背景に対応せねばならないならば,もう少し工夫が要るでしょう.
(例えば2値化結果から4本の線分を探すとか?)

イメージ説明

テスト時のコード.C++ですが.

C++

1int main() 2{ 3 //画像ロード.グレースケールで. 4 cv::Mat SrcImg = cv::imread( "A4s.png", cv::IMREAD_GRAYSCALE ); 5 if( SrcImg.empty() )return 0; 6 cv::imshow( "Src", SrcImg ); 7 8 //adaptiveThresholdに食わせてみる 9 cv::adaptiveThreshold( SrcImg, SrcImg, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, (SrcImg.cols/3)|0x01, 0 ); 10 cv::imshow( "AdpBin", SrcImg ); 11 12 //おまけのモルフォロジ 13 const int Iter = 3; 14 cv::erode( SrcImg, SrcImg, cv::Mat(), cv::Point(-1,-1), Iter ); 15 cv::dilate( SrcImg, SrcImg, cv::Mat(), cv::Point(-1,-1), Iter ); 16 cv::imshow( "Result", SrcImg ); 17 18 cv::waitKey(); 19 return 0; 20}

[追記]
てきとーに手作業でA4領域の赤線を消した画像を入力として,最後に findContoursをやってみた.

下図左側が↑と同じ処理を行った結果で,右側が,findContoursで得た塊のうち,でかいやつの輪郭を白で描画してみた結果.

イメージ説明

テストコードは findContours 部分が増えただけだが,一応全文掲載:

C++

1int main() 2{ 3 //画像ロード.グレースケールで. 4 cv::Mat Img = cv::imread( "A4s.png", cv::IMREAD_GRAYSCALE ); 5 if( Img.empty() )return 0; 6 cv::imshow( "Src", Img ); 7 8 //adaptiveThresholdに食わせてみる 9 cv::adaptiveThreshold( Img, Img, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, (Img.cols/3)|0x01, 0 ); 10 cv::imshow( "AdpBin", Img ); 11 12 //おまけのモルフォロジ 13 const int Iter = 3; 14 cv::erode( Img, Img, cv::Mat(), cv::Point(-1,-1), Iter ); 15 cv::dilate( Img, Img, cv::Mat(), cv::Point(-1,-1), Iter ); 16 cv::imshow( "Morph", Img ); 17 18 //findContoursで得られた,てきとーにでかい塊を描画してみる 19 std::vector< std::vector< cv::Point> > Conts; 20 cv::findContours( Img, Conts, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE ); 21 Img *= 0.4; 22 for( int i=0; i<Conts.size(); ++i ) 23 { 24 if( cv::contourArea( Conts[i] ) > 100*100 ) 25 { cv::drawContours( Img, Conts, i, cv::Scalar(255), 2 ); } 26 } 27 cv::imshow( "Conts", Img ); 28 29 cv::waitKey(); 30 return 0; 31}

投稿2021/07/26 01:58

編集2021/07/26 02:27
fana

総合スコア11708

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

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

hikari.13

2021/07/26 02:04

ご指摘ありがとうございます。 記入不足で大変申し訳ございませんでした。要望としては足の下敷いてあるA4用紙だけを囲うようにしたいと思っておりました。
fana

2021/07/26 02:10

ま,とりあえずこの結果例の右側みたいなのが得られさえすれば, あとは,contour検出なりラベリング処理なりで領域を取り出せば良いのではないかと. (余計な赤線が無い状態でやれば,大きく繋がった領域になるでしょうし)
fana

2021/07/26 02:28

…っていう話を追記しておいた.
hikari.13

2021/07/30 04:04

一度試してみます。ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問