这是如何使用openCV的minAreaRect函数完成的.它是用C语言编写的,但可能你很容易适应,因为几乎只使用了OpenCV函数.
cv::Mat input = cv::imread("../inputData/rectangles.png");
cv::Mat gray;
cv::cvtColor(input,gray,CV_BGR2GRAY);
// since your image has compression artifacts, we have to threshold the image
int threshold = 200;
cv::Mat mask = gray > threshold;
cv::imshow("mask", mask);
// extract contours
std::vector<:vector> > contours;
cv::findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for(int i=0; i
{
// fit bounding rectangle around contour
cv::RotatedRect rotatedRect = cv::minAreaRect(contours[i]);
// read points and angle
cv::Point2f rect_points[4];
rotatedRect.points( rect_points );
float angle = rotatedRect.angle; // angle
// read center of rotated rect
cv::Point2f center = rotatedRect.center; // center
// draw rotated rect
for(unsigned int j=0; j<4; ++j)
cv::line(input, rect_points[j], rect_points[(j+1)%4], cv::Scalar(0,255,0));
// draw center and print text
std::stringstream ss; ss << angle; // convert float to string
cv::circle(input, center, 5, cv::Scalar(0,255,0)); // draw center
cv::putText(input, ss.str(), center + cv::Point2f(-25,25), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(255,0,255)); // print angle
}
得到这个图像:
正如您所看到的,角度可能不是您想要的(因为它们随机使用较长或较小的线作为参考).
您可以改为提取矩形的长边并手动计算角度.
如果您选择旋转的rects的较长边并从中计算角度,它看起来像这样:
// choose the longer edge of the rotated rect to compute the angle
cv::Point2f edge1 = cv::Vec2f(rect_points[1].x, rect_points[1].y) - cv::Vec2f(rect_points[0].x, rect_points[0].y);
cv::Point2f edge2 = cv::Vec2f(rect_points[2].x, rect_points[2].y) - cv::Vec2f(rect_points[1].x, rect_points[1].y);
cv::Point2f usedEdge = edge1;
if(cv::norm(edge2) > cv::norm(edge1))
usedEdge = edge2;
cv::Point2f reference = cv::Vec2f(1,0); // horizontal edge
angle = 180.0f/CV_PI * acos((reference.x*usedEdge.x + reference.y*usedEdge.y) / (cv::norm(reference) *cv::norm(usedEdge)));
给出这个结果,这应该是你要找的!
编辑:看起来操作不使用他发布的输入图像,因为参考矩形中心位于图像之外.
使用此输入(手动重新调整但可能仍然不是最佳):
我得到那些结果(蓝点是op提供的参考矩形中心):
比较参考与检测:
reference (x,y,angle) detection (x,y,angle)
(320,240,0) (320, 240, 180) // angle 180 is equal to angle 0 for lines
(75,175,90) (73.5, 174.5, 90)
(279,401,170) (279.002, 401.824, 169.992)
(507,379,61) (507.842, 379.75, 61.1443)
(545,95,135) (545.75, 94.25, 135)
(307,79,37) (306.756, 77.8384, 37.1042)
我很乐意看到REAL输入图像,也许结果会更好.