Ответ 1
Входные изображения, которые вы нам дали, довольно просты в работе:
Первый шаг изолировать желтые капли от всего остального, и простая задача сегментации цвета может выполнить эту задачу. Вы можете посмотреть Сегментация и обнаружение объектов по цвету или Отслеживание цветные объекты в OpenCV, чтобы иметь представление о том, как это сделать.
Затем, время для слияния капли. Одним из методов, который может быть полезен, является ограничивающий прямоугольник, чтобы поместить все капли внутри прямоугольника. Обратите внимание на изображения ниже, что есть зеленый прямоугольник, окружающий капли:
После этого все, что вам нужно сделать, это заполнить прямоугольник цветом по вашему выбору, тем самым соединяя все капли. Я оставляю это в качестве домашней работы для вас.
Это самый быстрый и простой подход, о котором я мог думать. Следующий код демонстрирует, как добиться того, что я только что описал:
#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;
}