Один подход состоит в пороговым входного изображения с cv::inRange()
:
cv::Mat image = cv::imread(argv[1]);
if (image.empty())
{
std::cout << "!!! Failed imread()" << std::endl;
return -1;
}
cv::Mat red_image;
cv::inRange(image, cv::Scalar(40, 0, 180), cv::Scalar(135, 110, 255), red_image);
//cv::imwrite("out1.png", red_image);
Выходы:
Мы можем использовать cv::findContours
, чтобы получить контуры пороговую образ для творчества е ограничивающей коробки для них, which is a technique described here:
std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(red_image,
contours,
hierarchy,
CV_RETR_TREE,
CV_CHAIN_APPROX_SIMPLE,
cv::Point(0, 0));
std::vector<std::vector<cv::Point> > contours_poly(contours.size());
std::vector<cv::Rect> boundRect(contours.size());
for(int i = 0; i < contours.size(); i++)
{
cv::approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 3, true);
boundRect[i] = cv::boundingRect(cv::Mat(contours_poly[i]));
}
// Debug purposes: draw bonding rects
//cv::Mat tmp = cv::Mat::zeros(red_image.size(), CV_8UC3);
//for(int i = 0; i< contours.size(); i++)
// rectangle(tmp, boundRect[i].tl(), boundRect[i].br(), cv::Scalar(0, 255, 0), 2, 8, 0);
//cv::imwrite("out2.png", tmp);
Выход:
Все отображаемые на изображении выше, хранятся в виде cv::Rect
объекта внутри boundRect
вектора прямоугольниками.Каждый rectangle состоит из 2 противоположных cv::Point
объектов, поэтому мы итерация по этому вектору, чтобы создать новый вектор, состоящие только из cv::Point
объектов:
// Two opposite cv::Point can be used to draw a rectangle.
// Iterate on the cv::Rect vector and retrieve all cv::Point
// and store them in a cv::Point vector.
std::vector<cv::Point> rect_points;
for(int i = 0; i < contours.size(); i++)
{
rect_points.push_back(boundRect[i].tl());
rect_points.push_back(boundRect[i].br());
}
//cv::Mat drawing = cv::Mat::zeros(red_image.size(), CV_8UC3);
cv::Mat drawing = image.clone();
логика, чтобы найти белые квадраты: предположу, что 2 пикселя в пределах 25х25 расстояние друг от друга определяют белый квадрат:
// Draw a rectangle when 2 points are less than 25x25 pixels of
// distance from each other
for(int i = 0; i < rect_points.size(); i++)
{
for(int j = 0; j < rect_points.size(); j++)
{
if (i == j)
continue;
int x_distance = (rect_points[i].x - rect_points[j].x);
if (x_distance < 0)
x_distance *= -1;
int y_distance = (rect_points[i].y - rect_points[j].y);
if (y_distance < 0)
y_distance *= -1;
if ((x_distance < 25) && (y_distance < 25))
{
std::cout << "Drawing rectangle " << i << " from "
<< rect_points[i] << " to " << rect_points[j]
<< " distance: " << x_distance << "x" << y_distance << std::endl;
cv::rectangle(drawing,
rect_points[i],
rect_points[j],
cv::Scalar(255, 50, 0),
2);
break;
}
}
}
//cv::imwrite("out3.png", drawing);
cv::imshow("white rectangles", drawing);
cv::waitKey();
Выход:
Этот алгоритм довольно сырой и пропускает два белых квадрата внизу, потому что под ними нет красных стен, только над ними.
Так я оставляю это до вас, чтобы улучшить этот подход :)
удачи.
Ну, белые в середине красных, arent они? Пойдите для этого. Найдите белый цвет между красными. Или найдите разрыв между красными и проверьте, белый ли он. –
@AnderBiguri Это звучит правильно, я все еще рисую пустую информацию о том, как реализовать это в OpenCV. – salgarcia
. Пораженное изображение, которое вы использовали, не является результатом обработки этого входного изображения. Они не совпадают :) – karlphillip