2013-04-01 46 views
7

私は、人工的なマーカーを見つけなければならないオフィスインテリア(詳細)のウェブカメラストリームからフィードしたOpenCVアプリケーションを持っています。マーカーは白い背景の黒い四角です。私はCannyを使ってエッジを見つけ、輪郭作成のためのcvFindContoursを作り、次にapproxPolyDPとcoを使います。フィルターをかけて候補を見つけて、ローカルヒストグラムを使ってさらにフィルタリングします。bla bla bla ...Cannyの輪郭を輪郭に変換するOpenCV

これは多かれ少なかれ、私がしたいとは限りません。 Cannyが閉じられていない行を作成したとしても、FindContoursは常に閉じたループを返します。私はループを形成するラインの両側を歩く輪郭を得る。 Canny画像(私のマーカー)の閉じた辺については、内側に1つ、外側にもう1つの等高線があります。 私は、この操作で問題が発生する必要があります。

  • 私は各マーカーの2つの輪郭(その深刻ではない)

  • 最も些細なフィルタリングが使用できない(非閉じた輪郭を拒否)

  • を取得

私の質問:非閉じた輪郭を非閉じたCannyエッジにすることは可能ですか? 上記の2つの問題を解決するための標準的な方法は何ですか?

Cannyは非常に優れたツールですが、2Dのb/w画像を簡単に処理できるものに変換する方法が必要です。コンポーネントの歩いている順番にすべてのピクセルをリストした接続されたコンポーネントのようなもの。だから、私はループをフィルタリングし、approxPolyDPにフィードすることができます。

更新:いくつかの重要なディテールが欠落していました。マーカーは任意の向き(カメラに直面しておらず、直角ではありません)である可能性があります。実際には、私がやっているのは3D投影の推定ですマーカー。

答えて

10

問題の2つの問題に対してクリーンで簡単な解決策が見つかりました。このトリックは、(findCountoursの)2レベルの階層生成を可能にし、親を持つ等高線を探します。閉じたCannyの辺の内側の輪郭を返します。 閉じていないエッジは自動的に破棄され、各マーカーは単一の輪郭になります。

vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
findContours(CannyImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0,0)); 
for (unsigned int i=0; i<contours.size(); i++) 
    if (hierarchy[i][3] >= 0) //has parent, inner (hole) contour of a closed edge (looks good) 
     drawContours(contourImage, contours, i, Scalar(255, 0, 0), 1, 8); 

また、周りに他の方法で動作し、それは次のようになります。子供を持つ輪郭を探し(階層[i]の[2]> = 0)が、私の場合には、親のチェックは、より良い結果が得られます。

+2

findContours()とdrawContours()は必ず同じイメージで動作するとは限りません。輪郭画像をオーバードローする。この編集では、findContours()の入力がCanny()から来ているという情報も取り除かれました。 –

1

これはどのように行うのですか 1.エッジ検出のためのCanny 2.エッジトランスフォーマーを使用してエッジを検出します。 3. 90°の角度を持つ2つのエッジを検出します。

+0

正面に直面している長方形の場合はお勧めですが、残念ながら私はそれらを任意の方向で検出しなければなりません。実際に私がやっている仕事は、(既知の固有のカムパラメータを使って)3D空間でマーカの向きを推定することです。 –

+0

OpenSURFを使って任意の向きでマーカーを検出することができます。 –

2

は、私はそれを解決することができませんでした重複輪郭と同じ問題を抱えていたとさえ拡張および浸食さ:

Mat src=imread("E:\\test.bmp"),gry,bin,nor,dil,erd; 
GaussianBlur(src, nor, Size(5,5),0); 
cvtColor(nor,gry,CV_BGR2GRAY); 
Canny(gry,bin,100,150,5,true); 
dilate(bin,dil,Mat()); 
erode(dil,erd,Mat()); 
Mat tmp=bin.clone(); 
vector<vector<Point>> conts; 
vector<Vec4i> hier; 
findContours(tmp,conts,hier,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE); 

この画像(test.bmp)3つの輪郭が含まれていますが、findContoursは6を返して! Iは解決しきい値と問題を使用:

Mat src=imread("E:\\test.bmp"),gry,bin,nor,dil,erd; 
GaussianBlur(src, nor, Size(5,5),0); 
cvtColor(nor,gry,CV_BGR2GRAY); 
threshold(gry,bin,0,255,THRESH_BINARY+THRESH_OTSU);  
vector<vector<Point>> conts; 
vector<Vec4i> hier; 
findContours(bin,conts,hier,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE); 

今では1つの画像の境界(インデックス0を有する輪郭)であり、容易にスキップすることができる4つの輪郭を返します。