2012-06-28 7 views
8

私は、画像処理技術を使ってさまざまなオブジェクトとその長さを識別するプロジェクトを行っています。私はjavaCVとOpenCVの多くの例を見ています。しかし残念ながら私は多角形のT字形を特定できませんでした。opencvまたはjavacvを使ってポリゴンを特定する方法は?

次の矩形識別方法を使用しようとしましたが、失敗しました。

public static CvSeq findSquares(final IplImage src, CvMemStorage storage) 
{ 

CvSeq squares = new CvContour(); 
squares = cvCreateSeq(0, sizeof(CvContour.class), sizeof(CvSeq.class), storage); 

IplImage pyr = null, timg = null, gray = null, tgray; 
timg = cvCloneImage(src); 

CvSize sz = cvSize(src.width() & -2, src.height() & -2); 
tgray = cvCreateImage(sz, src.depth(), 1); 
gray = cvCreateImage(sz, src.depth(), 1); 
pyr = cvCreateImage(cvSize(sz.width()/2, sz.height()/2), src.depth(), src.nChannels()); 

// down-scale and upscale the image to filter out the noise 
cvPyrDown(timg, pyr, CV_GAUSSIAN_5x5); 
cvPyrUp(pyr, timg, CV_GAUSSIAN_5x5); 
cvSaveImage("ha.jpg", timg); 
CvSeq contours = new CvContour(); 
// request closing of the application when the image window is closed 
// show image on window 
// find squares in every color plane of the image 
for(int c = 0; c < 3; c++) 
{ 
    IplImage channels[] = {cvCreateImage(sz, 8, 1), cvCreateImage(sz, 8, 1), cvCreateImage(sz, 8, 1)}; 
    channels[c] = cvCreateImage(sz, 8, 1); 
    if(src.nChannels() > 1){ 
     cvSplit(timg, channels[0], channels[1], channels[2], null); 
    }else{ 
     tgray = cvCloneImage(timg); 
    } 
    tgray = channels[c]; 
    // try several threshold levels 
    for(int l = 0; l < N; l++) 
    { 
    //    hack: use Canny instead of zero threshold level. 
    //    Canny helps to catch squares with gradient shading 
     if(l == 0) 
     { 
    //    apply Canny. Take the upper threshold from slider 
    //    and set the lower to 0 (which forces edges merging) 
         cvCanny(tgray, gray, 0, thresh, 5); 
    //     dilate canny output to remove potential 
    //    // holes between edge segments 
         cvDilate(gray, gray, null, 1); 
       } 
      else 
     { 
    //    apply threshold if l!=0: 
         cvThreshold(tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY); 
      } 
     //   find contours and store them all as a list 
         cvFindContours(gray, storage, contours, sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

         CvSeq approx; 

     //   test each contour 
         while (contours != null && !contours.isNull()) { 
         if (contours.elem_size() > 0) { 
          approx = cvApproxPoly(contours, Loader.sizeof(CvContour.class),storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0); 
        if(approx.total() == 4 
          && 
          Math.abs(cvContourArea(approx, CV_WHOLE_SEQ, 0)) > 1000 && 
         cvCheckContourConvexity(approx) != 0 
         ){ 
         double maxCosine = 0; 
         // 
         for(int j = 2; j < 5; j++) 
         { 
      // find the maximum cosine of the angle between joint edges 
               double cosine = Math.abs(angle(new CvPoint(cvGetSeqElem(approx, j%4)), new CvPoint(cvGetSeqElem(approx, j-2)), new CvPoint(cvGetSeqElem(approx, j-1)))); 
               maxCosine = Math.max(maxCosine, cosine); 
         } 
         if(maxCosine < 0.2){ 
           CvRect x=cvBoundingRect(approx, l); 
           if((x.width()*x.height())<5000){ 
            System.out.println("Width : "+x.width()+" Height : "+x.height()); 
          cvSeqPush(squares, approx); 
            //System.out.println(x); 
           } 
         } 
        } 
       } 
       contours = contours.h_next(); 
      } 
     contours = new CvContour(); 
    } 
} 
return squares; 
} 

画像からT字形を識別するためにこの方法を変更してください。入力画像はこのようなものです。

enter image description here

これは、私はあなたが輪郭を見つけ、CvApproxPoly()を使用する方がよいかもしれません

enter image description here

+0

それはあなたの入力イメージですか? – ArtemStorozhuk

+0

この画像のあなたの識別の必要な部分は? –

+0

私は今、それについての詳細が含まれている質問を更新しました。 –

答えて

6

私はあなたの問題への解決策を見つけた:グレースケールへ

  • コンバート画像:

grayscale image

  • しきい値を行い(1ビットの画像に変換):

filled image

ヒント:はOpenCVの中で輪郭を埋めるために

2bit image

  • 輪郭を検索し、それらを埋めますに-1thicknessパラメータとして使用してください機能。

    • は、拡張を行うと同じカーネルを持つこの浸食後:
    result image

    そして、それはそれです!この後、あなたの画像がTの形をしていることがあなたにとって問題ではありません!

    生憎私はJavaCVを知らないが、私はあなたとC++コードを共有することができます:あなたはJavaCVにこのコードを変換することができますしたい場合:

    Mat src = imread("in.jpg"), gray; 
    
    cvtColor(src, gray, CV_BGR2GRAY); 
    
    threshold(gray, gray, 230, 255, THRESH_BINARY_INV); 
    
    vector<Vec4i> hierarchy; 
    vector<vector<Point> > contours; 
    
    findContours(gray, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 
    
    gray = Scalar::all(255); 
    for (size_t i=0; i<contours.size(); i++) 
    { 
        drawContours(gray, contours, i, Scalar(0), -1); 
    } 
    
    Mat element = getStructuringElement(MORPH_RECT, Size(2, 2), Point(1, 1)); 
    dilate(gray, gray, element); 
    erode(gray, gray, element); 
    
    imshow("window", gray); 
    

    ヒントを。これを行うにはthis tutorialを読んでください。

+0

このタイプのポリゴンの長さにはどうすればアクセスできますか? –

+1

@LBNConsまず、このポリゴンを特定する必要があります。あなたがそれをどうやってやることができるのか、多くの方法がありますポリゴンが検出された後は、 'approxPolyDP'関数を使用するよりも多かったのです。 – ArtemStorozhuk

+0

@Astor approxPolyDPメソッドは正確に8ポイントを提供しますか? –

1

を特定する必要がT字状です。この関数を使用して長方形hereを検索し、それをあなたのT形を見つけるために適合させるための良い例を見つけることができます。この例はOpenCVを使用して作成され、C++で記述されています。シーケンス内のすべてのポイントを通過する

for (int i = 0; i < cornerPoints->total; i++) { 
CvPoint *cornerPoints = (CvPoint*) cvGetSeqElem(cornerPoints, i); 
} 
+4

この簡単なコード例を教えてください。 –

+0

私はCvApproxPoly()メソッドを実行しましたが、CvSeqも返します。しかし、ポリゴンのエッジの座標を抽出する必要があります –

+0

輪郭上のすべての点からCvPointを作成したい場合は、forループを使用してすべての点を通過させることができます。私はこれを私の答えに加えました。 –

0

前処理

のに宿題のように聞こえる@Astorをもたらすには、間違いなく便利です。 しかし、私は幾分まだこの形状認識が画像処理と強く結びついていると思っています:形態学

テンプレートをT字型にしてから "畳み込み?テンプレートは前処理された結果を持つ。私は詳細を覚えていない、ちょうどTAGの形態とコンボルーションに関する調査

関連する問題