2012-04-23 27 views
5

ブロブ検出にfindContoursを使用します。今私は密接に類似した塊を合併するでしょう。ここでブロブ/輪郭をマージするには

は、いくつかのサンプル画像です:

enter image description hereenter image description hereenter image description here

は、通常のOpenCVで可能なことですか?

+0

あなたは投稿できますサンプル画像? – karlphillip

+0

画像を追加する方がよい。 imageshack.usでアップロードし、ここにリンクを張りましょう。同様に何を意味するのかを指定します。それは形が似ていますか?または同様の領域を持っている?等 –

+0

私はお互いの隣にある同様の形をマージしたいと思います。ここに3つの例があります(黄色のマーク)助けてくれてありがとう! [画像1](http://img713.imageshack.us/img713/2152/image1xg.png) [画像2](http://img32.imageshack.us/img32/2149/image2kl.png) [Image 3](http://img256.imageshack.us/img256/1000/image3jg.png) – rouge

答えて

3

入力画像は、あなたは私たちと仕事するのは簡単です与えた:

enter image description hereenter image description hereenter image description here

最初のステップは、は、他のすべてから黄色の塊を分離し、シンプルなカラーセグメンテーション技術は、これを達成することができますです仕事。方法については、Segmentation & Object Detection by colorまたはTracking colored objects in OpenCVをご覧ください。

enter image description hereenter image description hereenter image description here

その後、それはブロブをマージする時間です。特に有用な1つの技法は、bounding boxからまでのすべてのブロブを長方形の中に置くことです。ブロブを囲む緑の四角があることを、以下の画像に注目してください:この後

enter image description hereenter image description hereenter image description here

は、すべてを行う必要がは、このように接続し、お好みの色で矩形を塗りつぶしていますすべてのブロブ私はこの最後を宿題のままにしておきます。

これは私が考えることができる最も簡単で簡単なアプローチです。次のコードは、私が説明したものを達成する方法を示しています。

#include <cv.h> 
#include <highgui.h> 

#include <iostream> 
#include <vector> 

int main(int argc, char* argv[]) 
{ 
    cv::Mat img = cv::imread(argv[1]); 
    if (!img.data) 
    { 
     std::cout "!!! Failed to open file: " << argv[1] << std::endl; 
     return 0; 
    } 

    // Convert RGB Mat into HSV color space 
    cv::Mat hsv; 
    cv::cvtColor(img, hsv, CV_BGR2HSV); 

    // Split HSV Mat into HSV components 
    std::vector<cv::Mat> v; 
    cv::split(hsv,v); 

    // Erase pixels with low saturation 
    int min_sat = 70; 
    cv::threshold(v[1], v[1], min_sat, 255, cv::THRESH_BINARY); 

    /* Work with the saturated image from now on */ 

// Erode could provide some enhancement, but I'm not sure. 
// cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); 
// cv::erode(v[1], v[1], element); 

    // Store the set of points in the image before assembling the bounding box 
    std::vector<cv::Point> points; 
    cv::Mat_<uchar>::iterator it = v[1].begin<uchar>(); 
    cv::Mat_<uchar>::iterator end = v[1].end<uchar>(); 
    for (; it != end; ++it) 
    { 
     if (*it) points.push_back(it.pos()); 
    } 

    // Compute minimal bounding box 
    cv::RotatedRect box = cv::minAreaRect(cv::Mat(points)); 

    // Display bounding box on the original image 
    cv::Point2f vertices[4]; 
    box.points(vertices); 
    for (int i = 0; i < 4; ++i) 
    { 
      cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA); 
    } 

    cv::imshow("box", img); 
    //cv::imwrite(argv[2], img); 

    cvWaitKey(0); 

    return 0; 
} 
+0

ですが、あなたは私を少し誤解しました。黄色の塊は本当に黄色ではありません。私はちょうど私がマージしようとするブロブを魔女に見せるためにそれらを着色しました。私は他のブロブを分離するためにカラーセグメンテーションを使用することができません。多分私がマージするのを好まないいくつかの他の大きなブロブの魔女がいるので、エリアのような情報はうまくいかないでしょう... – rouge

+0

Bah! = \は後で別のことを考えます。 – karlphillip

+0

あなたは最大のブロブに興味がありますか? – karlphillip

2

私はそれをやったと思いますが、あなたのプログラムの詳細のおかげで私はこの解決策を見つけた:(コメントは歓迎されている)

vector<vector<Point> > contours; 
    vector<vector<Point> > tmp_contours; 
    findContours(detectedImg, tmp_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 

    vector<vector<Point> >::iterator it1; 
    it1 = tmp_contours.begin(); 

    Mat test; 
    test = Mat(FImage.size(), CV_32FC3); 

    while (it1 != tmp_contours.end()) { 
     vector<Point> approx1; 
     approxPolyDP(Mat(*it1), approx1, 3, true); 
     Rect box1 = boundingRect(approx1); 
     float area1 = contourArea(approx1); 



     if ((area1 > 50) && (area1 < 13000) && (box1.width < 100) && (box1.height < 120)) { 

      vector<vector<Point> >::iterator it2; 
      it2 = tmp_contours.begin(); 

      while (it2 != tmp_contours.end()) { 
       vector<Point> approx2; 
       approxPolyDP(Mat(*it2), approx2, 3, true); 

       Moments m1 = moments(Mat(approx1), false); 
       Moments m2 = moments(Mat(approx2), false); 
       float x1 = m1.m10/m1.m00; 
       float y1 = m1.m01/m1.m00; 
       float x2 = m2.m10/m2.m00; 
       float y2 = m2.m01/m2.m00; 

       vector<Point> dist; 
       dist.push_back(Point(x1, y1)); 
       dist.push_back(Point(x2, y2)); 
       float d = arcLength(dist, false); 

       Rect box2 = boundingRect(approx2); 
       if (box1 != box2) { 

        if (d < 25) { 
         //Method to merge the vectors 
         approx1 = mergePoints(approx1, approx2); 
        } 

       } 
       ++it2; 

      } 
      Rect b = boundingRect(approx1); 
      rectangle(test, b, CV_RGB(125, 255, 0), 2); 
      contours.push_back(approx1); 
     } 
     ++it1; 
    }