2012-04-23 10 views
5

Uso findContours para la detección de blobs. Ahora fusionaría blobs similares y cercanos.Cómo puedo fusionar blobs/contornos

Estas son algunas imágenes de muestra:

enter image description hereenter image description hereenter image description here

es que es posible con OpenCV normal?

+0

Se puede publicar una ¿Imagen de muestra? – karlphillip

+0

Mejor si agrega una imagen. Subir en imageshack.us y dar el enlace aquí. También especifique a qué se refiere con similar. ¿Es similar en forma? ¿O tiene un área similar? etc –

+0

ok me gustaría fusionar formas similares que están una al lado de la otra. Aquí hay tres ejemplos (marque como amarillo) ¡gracias por la ayuda! [Imagen 1] (http://img713.imageshack.us/img713/2152/image1xg.png) [Imagen 2] (http://img32.imageshack.us/img32/2149/image2kl.png) [Imagen 3] (http://img256.imageshack.us/img256/1000/image3jg.png) – rouge

Respuesta

3

Las imágenes de entrada que nos dieron son bastante fáciles de trabajar con:

enter image description hereenter image description hereenter image description here

El primer paso es aislar las manchas amarillas de todo lo demás y una técnica simple de color segmentación puede lograr esto tarea. Puede echar un vistazo a Segmentation & Object Detection by color o Tracking colored objects in OpenCV para tener una idea de cómo hacerlo.

enter image description hereenter image description hereenter image description here

Entonces, es el momento de fusionar las manchas. Una técnica en particular que puede ser útil es bounding box, a poner todos los blobs dentro de un rectángulo. Observe en las imágenes a continuación, que no es un rectángulo verde que rodea las gotas:

enter image description hereenter image description hereenter image description here

Después de eso, todo lo que necesita hacer es llenar el rectángulo con el color de su elección, conectando así todos los blobs. Dejo esto último como tarea para ti.

Este es el enfoque más rápido y simple que pude pensar. El código siguiente muestra cómo lograr lo que acabo de describir:

#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

gracias por su respuesta ... pero me malentendió un poco. Las manchas amarillas no son realmente amarillas.Acabo de colorearlos para mostrarte blobs de bruja que trataría de fusionar. así que no puedo usar la segmentación del color para aislar los otros blobs. También la información como área no funcionará porque tal vez haya otras burbujas más grandes que no me gustaría fusionar ... – rouge

+0

¡Bah! = \ pensaré en algo más más tarde. – karlphillip

+0

Le interesan los blobs más grandes, ¿verdad? – karlphillip

2

creo que lo hice, gracias a sus detalles del programa que encontré esta solución: (comentarios son bienvenidos)

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; 
    } 
Cuestiones relacionadas