OpenCV官网
#include
#include
using namespace cv;
using namespace std;
Mat src_gray;
int thresh = 100;
RNG rng(12345);
void thresh_callback(int, void*);
int main(void)
{
Mat src = imread("../res/balloon.png");
if(src.empty())
{
cout << "can't load image" << endl;
return -1;
}
cvtColor(src, src_gray, cv::COLOR_BGR2GRAY);
blur(src_gray, src_gray, Size(3,3));
const char* source_window = "Source";
namedWindow(source_window);
imshow(source_window, src);
const int max_thresh =255;
createTrackbar("canny thresh:", source_window, &thresh, max_thresh, thresh_callback);
thresh_callback(0,0);
waitKey();
return 0;
};
void thresh_callback(int, void*)
{
Mat canny_output;
Canny(src_gray, canny_output, thresh, thresh*2);
vector<vector<Point>> contours;
findContours(canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE); //从canny输出得到轮廓图
vector<vector<Point>> contours_poly(contours.size()); //近似轮廓的多边形
vector<Rect> boundRect (contours.size()); //矩形
vector<Point2f> centers(contours.size()); // 圆的中心
vector<float> radius(contours.size()); //圆的半径
for(size_t i=0; i<contours.size();i++) //对于每个轮廓都进行以下操作
{
cv::approxPolyDP(contours[i], contours_poly[i], 3, true); //将轮廓近似到多边形,最大距离不大于3
boundRect[i] = cv::boundingRect(contours_poly[i]); //得到 能包围多边形的最小矩形
cv::minEnclosingCircle(contours_poly[i], centers[i], radius[i]); //得到能包围多边形的最小圆
}
//开始画图, 多边形、圆、矩形
Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
for(size_t i=0; i<contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0,256), rng.uniform(0, 256), rng.uniform(0,256));
drawContours(drawing, contours_poly, (int)i, color);
cv::rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color,2);
cv::circle(drawing, centers[i], (int)radius[i], color, 2);
}
imshow("Contours", drawing);
}
结果:
void cv::approxPolyDP
( InputArray curve, //输入的轮廓,存在std::vector 或者Mat
OutputArray approxCurve, // 输出的近似, 和输入类型一样
double epsilon, // 指定近似的误差, 近似的多边行和轮廓之间最大距离
bool closed // true: 近似多边形是closed,第一个点和最后一个点连起来的, false: not closed
)
( InputArray points, //输入点, 存在std::vector<> or Mat
Point2f & center, //圆心
float & radius //半径
)
double cv::minEnclosingTriangle
(
InputArray points, //Input vector of 2D points with depth CV_32S or CV_32F, stored in std::vector<> or Mat
OutputArray //triangle Output vector of three 2D points defining the vertices of the triangle. The depth of the OutputArray must be CV_32F.
)
RotatedRect cv::minAreaRect ( InputArray points )
值得注意的是, 当一组点的一部分接近边界的时候,所得到的矩形的顶点有可能是负数
RotatedRect cv::fitEllipse ( InputArray points )
值得注意的是, 当一组点的一部分接近边界的时候,所得到的矩形的顶点有可能是负数,椭圆就是矩形内接椭圆
void thresh_callback(int, void* )
{
Mat canny_output;
Canny( src_gray, canny_output, thresh, thresh*2 );
vector<vector<Point> > contours;
findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
vector<RotatedRect> minRect( contours.size() );
vector<RotatedRect> minEllipse( contours.size() );
for( size_t i = 0; i < contours.size(); i++ )
{
minRect[i] = minAreaRect( contours[i] );
if( contours[i].size() > 5 )
{
minEllipse[i] = fitEllipse( contours[i] );
}
}
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
for( size_t i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );
// contour
drawContours( drawing, contours, (int)i, color );
// ellipse
ellipse( drawing, minEllipse[i], color, 2 );
// rotated rectangle
Point2f rect_points[4];
minRect[i].points( rect_points );
for ( int j = 0; j < 4; j++ )
{
line( drawing, rect_points[j], rect_points[(j+1)%4], color );
}
}
imshow( "Contours", drawing );
}