OpenCV:检查像素是否在边界矩形内,由等高线分隔
我有一个形象面具,有一些我从Canny那里得到的轮廓。 我可以计算一个边界矩形(具有固定的给定角度)。
现在我需要将这两个区域分离到该矩形的左侧和右侧。 我怎样才能做到这一点?
请注意,我想要处理矩形内的区域,而不是轮廓的像素。
编辑
这是我如何从掩码获取每个边界矩形:
cv::Mat img_edges; // mask with contours
// Apply clustering to the edge mask from here
// http://stackoverflow.com/questions/33825249/opencv-euclidean-clustering-vs-findcontours?noredirect=1#comment55433731_33825249
// Find boundary rectangle
for (auto &contour: contours) { // Iterate over every contour cluster
cv::Mat Srot = cv::getRotationMatrix2D(cv::Point2f(float(img_edges.cols) / 2., float(img_edges.rows) / 2.), -ILLUMINATION_ANGLE_DEG, 1.0);
cv::transform(contour, contour, Srot);
float min_x, min_y, max_x, max_y;
min_x = min_y = std::numeric_limits<float>::max();
max_x = max_y = -std::numeric_limits<float>::max();
// Simply find edges of aligned rectangle, then rotate back by inverse of Srot
}
好吧,让我们假设我可以获得连接组件。 我该如何继续?
从评论到问题,我们同意这个程序应该适用于轴对齐的矩形。 这不会失去一般性,因为您可以将旋转的矩形旋转为轴对齐,应用此过程,然后再旋转点。
从具有一些边缘的示例图像开始,如:
你可以得到像这样的东西,其中蓝色是由边缘分隔的边界框中的左边部分,红色是右边部分:
这个算法可能不是最聪明的做法,但在实践中可以正常工作。
找到每条边的边界框后:
tmp
,再加上左边的1列和右边的1。 这将使算法对特定情况具有鲁棒性。 tmp
。 floodFill
算法来查找左边的点。 种子是tmp
左上角。 floodFill
算法找到正确的点。 种子是tmp
右上角。 这里的评论代码,如果有什么不明确的话,请ping我:
#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
void separateAreas(const Rect& roi, const vector<Point>& points, vector<Point>& left, vector<Point>& right)
{
left.clear();
right.clear();
// Temporary matrix
// 0 : background pixels
// 1 : boundary pixels
// 2 : left pixels
// 3 : right pixels
Mat1b tmp(roi.height, roi.width + 2, uchar(0));
// Shift points to roi origin, i.e tmp(0,1)
vector<Point> pts(points);
for (int i = 0; i < points.size(); ++i)
{
pts[i] -= roi.tl();
// Draw boundary on tmp matrix
tmp(pts[i] + Point(1,0)) = 1;
}
// Fill left area, seed top left point
floodFill(tmp, Point(0, 0), Scalar(2));
// Fill right area, seed top right point
floodFill(tmp, Point(tmp.cols-1, 0), Scalar(3));
// Find left and right points
findNonZero(tmp.colRange(1, tmp.cols - 1) == 2, left);
findNonZero(tmp.colRange(1, tmp.cols - 1) == 3, right);
// Shift back
for (int i = 0; i < left.size(); ++i)
{
left[i] += roi.tl();
}
for (int i = 0; i < right.size(); ++i)
{
right[i] += roi.tl();
}
}
int main()
{
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
Mat3b res;
cvtColor(img, res, COLOR_GRAY2BGR);
vector<vector<Point>> contours;
findContours(img.clone(), contours, RETR_LIST, CV_CHAIN_APPROX_NONE);
for (int i = 0; i < contours.size(); ++i)
{
Rect roi = boundingRect(contours[i]);
//rectangle(res, roi, Scalar(0,255,0));
vector<Point> left, right;
separateAreas(roi, contours[i], left, right);
// Draw areas on res
for (int j = 0; j < left.size(); ++j)
{
res(left[j]) = Vec3b(255,0,0); // Blue for left
}
for (int j = 0; j < right.size(); ++j)
{
res(right[j]) = Vec3b(0, 0, 255); // Red for right
}
}
imshow("Image", img);
imshow("Result", res);
waitKey();
return 0;
}
链接地址: http://www.djcxy.com/p/89725.html
上一篇: OpenCV: check if pixel is within bounding rectangle, separated by contour line
下一篇: drawing a rectangle on an image after identifying the area using ROI (OpenCV)