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:
es que es posible con OpenCV normal?
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:
es que es posible con OpenCV normal?
Las imágenes de entrada que nos dieron son bastante fáciles de trabajar con:
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.
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:
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;
}
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
¡Bah! = \ pensaré en algo más más tarde. – karlphillip
Le interesan los blobs más grandes, ¿verdad? – karlphillip
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;
}
Se puede publicar una ¿Imagen de muestra? – karlphillip
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 –
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