Я использую findContours
для обнаружения blob. Теперь я бы объединил близкие и похожие капли вместе.Как слить капли/контуры
Вот некоторые примеры изображений:
это возможно с нормальным OpenCV?
Я использую findContours
для обнаружения blob. Теперь я бы объединил близкие и похожие капли вместе.Как слить капли/контуры
Вот некоторые примеры изображений:
это возможно с нормальным OpenCV?
входные изображения, которые вы дали нам довольно легко работать:
Первый шаг изолировать желтые пятна от всего остального и простой метод цветовой сегментации может сделать это задача. Вы можете взглянуть на Segmentation & Object Detection by color или Tracking colored objects in OpenCV, чтобы получить представление о том, как это сделать.
Затем пришло время объединить сгустки. Одним из методов, который может быть полезным, является bounding box, до положить все капли внутри прямоугольника. Обратите внимание на изображениях ниже, что есть зеленый прямоугольник, окружающий сгустки:
После этого, все, что вам нужно сделать, это заполнить прямоугольник с цветом вашего выбора, таким образом соединяя все капли. Я оставляю это в качестве домашней работы для вас.
Это самый быстрый и простой подход, о котором я мог думать. Следующий код демонстрирует, как добиться того, что я только что описал:
#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;
}
thx для вашего ответа ... но вы меня немного поняли. Желтые капли не очень желтые.Я просто покрасил их, чтобы показать вам пузыри ведьмы, которые я попытаюсь объединить. поэтому я не могу использовать сегментацию цвета для выделения других блоков. Кроме того, информация, подобная области, не будет работать, потому что, возможно, есть некоторые другие большие капли, которые мне не нравятся, чтобы объединиться ... – rouge
Bah! = \ подумать о чем-то еще позже. – karlphillip
Вас интересуют самые большие капли, не так ли? – karlphillip
я думаю, что я сделал это, благодаря вашей подробной информации о программе я нашел это решение: (комментарии приветствуются)
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;
}
Вы можете оставить образ образца? – karlphillip
Лучше, если вы добавите изображение. Загрузите в imageshack.us и дайте ссылку здесь. Также укажите, что вы подразумеваете под похожим. Он похож по форме? Или имея подобную область? и т. д. –
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