2016-04-28 16 views
2

Iバイナリ画像形状分析は、他の形状から矩形を区別する

いくつかの可能な例を用いて(例えば半円のような)非矩形オブジェクトから矩形のオブジェクトを区別するために形状解析を実行しようとしている

四角形

enter image description hereenter image description here

非長方形

enter image description hereenter image description here

私のアルゴリズムは次のように動作します:

  1. は、輪郭を使用してオブジェクトマスクを抽出 - OpenCVの(上記の例で見ることができるよう)
  2. は、形状の実行しますオブジェクトが矩形であるかどうかを検出するために統計を分析または計算する

これまでのところ、私は偏心と矩形性の対策を試みました。

例:理想的には、四角形は長方形の場合のみ高くする必要があります。私の実験では、矩形や円形のオブジェクトに対しても同様の矩形性が得られることがあります。したがって、信頼できるものではないため、この測定値は分析に使用できません。

偏心で同じ問題が発生します。理想的には、円の偏心はゼロであり、長方形のオブジェクトの円は非常に高いはずです。しかし、矩形や円では非常に似ていることが分かります。

オブジェクトがほぼ矩形であるかどうかを知る方法はありますか?

すべてのヘルプは本当に私はあなたがapproxPolyDPを使用することができると思います

+0

"うまくいく"、 "堅牢" と "正確に" を定義してください。分析コードはどのように見えますか?期待される結果は何ですか?あなたが今得ている実際の結果は何ですか? –

+0

こんにちは、私は質問を編集し、詳細を提供しました – user1388142

答えて

2

を理解されるであろう。私はC++でプログラムを提供しています。私はPythonで簡単に翻訳できると思います。アイデアは、実際の輪郭に近似する4つのコーナーを持つ形状を探してから、4つの角度(コーナー角度)を計算します。輪郭点の数が新しい輪郭と実際の輪郭との間の4よりも大きい間に増加する。 矩形でないと思った後に、しきい値角度(90 +/- x°)を選択する必要があります。 前の写真有り

#include "opencv2/opencv.hpp" 
#include <iostream> 

using namespace cv; 
using namespace std; 


int main(int argc, char **argv) 
{ 
vector<String> fileName; 
fileName.push_back("2nrTo.jpg"); 
fileName.push_back("G3I4t.jpg"); 
fileName.push_back("Q4ZtM.jpg"); 
fileName.push_back("vWgKx.jpg"); 
for (int i = 0; i < static_cast<int>(fileName.size()); i++) 
{ 
    Mat mThresh; 
    Mat m=imread(fileName[i],CV_LOAD_IMAGE_GRAYSCALE); 
    Mat mc; 
    vector<vector<Point> > contours; 
    vector<Vec4i> hierarchy; 
    threshold(m,mThresh,80,255,THRESH_BINARY); 
    findContours(mThresh,contours,hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_NONE, cv::Point(0,0)); 
    cout << "Image " << fileName[i] << "\n"; 
    imshow(fileName[i],m); 
    mc = Mat::zeros(m.size(),CV_8UC3); 
    drawContours(mc,contours,0,Scalar(255,0,0),1); 
    vector<Point> approx; 
    double d=0; 
    do 
    { 
     d=d+1; 
     approxPolyDP(contours[0],approx,d,true); 
    } 
    while (approx.size()>4); 
    cout << "#vertices =" <<approx.size() << "\t error max= " <<d<<endl; 
    if (approx.size() == 4) 
    { 
     cout << "Angles\n"; 
     Point2d u(approx[1]-approx[0]),v(approx[2]-approx[1]),w(approx[3]-approx[2]),x(approx[3]-approx[0]); 
     cout<<acos(u.dot(v)/norm(u)/norm(v))<<"\n"; 
     cout<<acos(v.dot(w)/norm(v)/norm(w))<<"\n"; 
     cout<<acos(w.dot(x)/norm(w)/norm(x))<<"\n"; 
     cout<<acos(x.dot(u)/norm(x)/norm(u))<<"\n"; 

    } 
    else 
     cout << "looks like a triangle\n"; 
    contours.push_back(approx); 
    drawContours(mc,contours,contours.size()-1,Scalar(0,0,255),1); 
    imshow("Ctr",mc); 
    waitKey(); 
} 

return 0; 
} 

(悪い英語のため申し訳ありませんが)プログラムはthoses結果を与える:

Image 2nrTo.jpg 
#vertices =4  error max= 17 
Angles 
93.3283 
90.2247 
90 
93.553 
Image G3I4t.jpg 
#vertices =4  error max= 15 
Angles 
112.503 
46.3837 
110.346 
48.5412 
Image Q4ZtM.jpg 
#vertices =4  error max= 6 
Angles 
88.9191 
90.0297 
88.9488 
90 
Image vWgKx.jpg 
#vertices =4  error max= 49 
Angles 
87.0753 
117.999 
90.3148 
114.76 
+0

明確にするために。角度は右の2つの点の間で計算されます。あなたは少し論理を説明することができます!ありがとう – user1388142