opencv 之 外接多边形(矩形、圆、三角形、椭圆、多边形)使用详解
-
本文主要讲述opencv中的外接多边形的使用:
- 多边形近似
- 外接矩形、最小外接矩形
- 最小外接圆
- 外接三角形
- 椭圆拟合
- 凸包
-
将重点讲述最小外接矩形的使用
1. API介绍
#多边形近似
void cv::approxPolyDP(InputArray curve,
OutputArray approxCurve,
double epsilon,
bool closed )
Python:
cv.approxPolyDP(curve, epsilon, closed[, approxCurve] ) -> approxCurve
#计算点到多边形的距离或者判断是否在多边形内部
double cv::pointPolygonTest (InputArray contour,
Point2f pt,
bool measureDist )
Python:
cv.pointPolygonTest(contour, pt, measureDist) -> retval
#外接矩形
Rect cv::boundingRect(InputArray array)
Python:
cv.boundingRect(array) -> retval
#最小外接矩形
RotatedRect cv::minAreaRect (InputArray points)
Python:
cv.minAreaRect( points) -> retval
#求矩形交集
int cv::rotatedRectangleIntersection(const RotatedRect & rect1,
const RotatedRect & rect2,
OutputArray intersectingRegion )
Python:
cv.rotatedRectangleIntersection(rect1, rect2[, intersectingRegion] ) -> retval, intersectingRegion
#最小外接圆
void cv::minEnclosingCircle (InputArray points,
Point2f & center,
float & radius )
Python:
cv.minEnclosingCircle(points) -> center, radius
#最小外接三角形
double cv::minEnclosingTriangle (InputArray points,
OutputArray triangle)
Python:
cv.minEnclosingTriangle(points[, triangle] ) -> retval, triangle
#椭圆拟合
void cv::ellipse(InputOutputArray img,
Point center,
Size axes,
double angle,
double startAngle,
double endAngle,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0 )
Python:
cv.ellipse( img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]] ) -> img
cv.ellipse( img, box, color[, thickness[, lineType]] ) -> img
2. 例程
- 给一个opencv官方的例程:
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
static void help()
{
cout << "This program demonstrates finding the minimum enclosing box, triangle or circle of a set\n"
<< "of points using functions: minAreaRect() minEnclosingTriangle() minEnclosingCircle().\n"
<< "Random points are generated and then enclosed.\n\n"
<< "Press ESC, 'q' or 'Q' to exit and any other key to regenerate the set of points.\n\n";
}
int main(int /*argc*/, char** /*argv*/)
{
help();
Mat img(500, 500, CV_8UC3, Scalar::all(0));
RNG& rng = theRNG();
for (;;)
{
int i, count = rng.uniform(1, 101);
vector<Point> points;
// Generate a random set of points
for (i = 0; i < count; i++)
{
Point pt;
pt.x = rng.uniform(img.cols / 4, img.cols * 3 / 4);
pt.y = rng.uniform(img.rows / 4, img.rows * 3 / 4);
points.push_back(pt);
}
// Find the minimum area enclosing bounding box
Point2f vtx[4];
RotatedRect box = minAreaRect(points);
box.points(vtx);
// Find the minimum area enclosing triangle
vector<Point2f> triangle;
minEnclosingTriangle(points, triangle);
// Find the minimum area enclosing circle
Point2f center;
float radius = 0;
minEnclosingCircle(points, center, radius);
img = Scalar::all(0);
// Draw the points
for (i = 0; i < count; i++)
circle(img, points[i], 3, Scalar(0, 0, 255), FILLED, LINE_AA);
// Draw the bounding box
for (i = 0; i < 4; i++)
line(img, vtx[i], vtx[(i + 1) % 4], Scalar(0, 255, 0), 1, LINE_AA);
//绘制外接矩形
rectangle(img, box.boundingRect(), cv::Scalar(10, 100, 20), 2);
//也可以:
/*cv::Rect _rect = boundingRect(points);
rectangle(img, _rect, cv::Scalar(10, 100, 20), 2);*/
// Draw the triangle
for (i = 0; i < 3; i++)
line(img, triangle[i], triangle[(i + 1) % 3], Scalar(255, 255, 0), 1, LINE_AA);
// Draw the circle
circle(img, center, cvRound(radius), Scalar(0, 255, 255), 1, LINE_AA);
imshow("Rectangle, triangle & circle", img);
char key = (char)waitKey();
if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
break;
}
return 0;
}
- 过程图像如下:
- 椭圆拟合一般用于轮廓提取之后:
//获取拟合椭圆的外包围矩形
cv::RotatedRect rotate_rect = cv::fitEllipse(points);
//绘制拟合椭圆
cv::ellipse(image, rotate_rect, cv::Scalar(0, 255, 255), 2, 8);
- 凸包绘制
vector<Point> hull;
convexHull(points, hull, true);
img = Scalar::all(0);
for( i = 0; i < count; i++ )
circle(img, points[i], 3, Scalar(0, 0, 255), FILLED, LINE_AA);
polylines(img, hull, true, Scalar(0, 255, 0), 1, LINE_AA);
imshow("hull", img);
#多边形填充绘制:
polylines(img, hull, true, Scalar(0, 255, 0), -1, LINE_AA);
- 计算两个旋转矩形交集:
vector<Point2f> intersectingRegion;
rotatedRectangleIntersection(rect1, rect2, intersectingRegion);
3. 关于最小外接矩形
- C++版的最小外接矩形使用:
RotatedRect rect = minAreaRect(points);
float angle = rect.
box.points(vtx);
其接口返回值可读取如下:其中,其角度指的是width与物理坐标系y轴正方向逆时针所成的夹角
赋值时也可以读出如下数据:中心、角度、尺寸大小、外接矩形
- 画图详解一下吧:
- 想要看真实的效果图的话,可以参考:biubiubiu~
- 它也可以用于:
- python版本的最小外接矩形:
_rect = cv2.minAreaRect(conts_new[i])
(x, y), (w, h), ang = _rect
box = cv2.boxPoints(_rect)
# 标准化坐标到整数
box = np.int32(box)
cv2.drawContours(mask_c3, [box], 0, (int(bgr[0]), int(bgr[1]), int(bgr[2])),2)
- 还有一些想法,后边再补充吧