2012-04-23 2 views
5

Я использую findContours для обнаружения blob. Теперь я бы объединил близкие и похожие капли вместе.Как слить капли/контуры

Вот некоторые примеры изображений:

enter image description hereenter image description hereenter image description here

это возможно с нормальным OpenCV?

+0

Вы можете оставить образ образца? – karlphillip

+0

Лучше, если вы добавите изображение. Загрузите в imageshack.us и дайте ссылку здесь. Также укажите, что вы подразумеваете под похожим. Он похож по форме? Или имея подобную область? и т. д. –

+0

ok Я хотел бы объединить аналогичную фигуру, которая находится рядом друг с другом. Вот три примера (отметьте как желтый) спасибо за помощь! [Изображение 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

Затем пришло время объединить сгустки. Одним из методов, который может быть полезным, является 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

thx для вашего ответа ... но вы меня немного поняли. Желтые капли не очень желтые.Я просто покрасил их, чтобы показать вам пузыри ведьмы, которые я попытаюсь объединить. поэтому я не могу использовать сегментацию цвета для выделения других блоков. Кроме того, информация, подобная области, не будет работать, потому что, возможно, есть некоторые другие большие капли, которые мне не нравятся, чтобы объединиться ... – 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; 
    }