轮廓逼近与拟合
轮廓逼近
本节相关API
CV_EXPORTS_W void approxPolyDP( InputArray curve,
OutputArray approxCurve,
double epsilon, bool closed );
/** @brief Approximates a polygonal curve(s) with the specified precision.
The function cv::approxPolyDP approximates a curve or a polygon with another curve/polygon with less
vertices so that the distance between them is less or equal to the specified precision. It uses the
Douglas-Peucker algorithm <http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm>
@param curve Input vector of a 2D point stored in std::vector or Mat
@param approxCurve Result of the approximation. The type should match the type of the input curve.
@param epsilon Parameter specifying the approximation accuracy. This is the maximum distance
between the original curve and its approximation.
@param closed If true, the approximated curve is closed (its first and last vertices are
connected). Otherwise, it is not closed.
*/
实验效果:
椭圆拟合
相关API
CV_EXPORTS_W RotatedRect fitEllipse( InputArray points );
/** @brief Fits an ellipse around a set of 2D points.
The function calculates the ellipse that fits (in a least-squares sense) a set of 2D points best of
all. It returns the rotated rectangle in which the ellipse is inscribed. The first algorithm described by @cite Fitzgibbon95
is used. Developer should keep in mind that it is possible that the returned
ellipse/rotatedRect data contains negative indices, due to the data points being close to the
border of the containing Mat element.
@param points Input 2D point set, stored in std::vector\<\> or Mat
*/
实验效果:
本节代码地址:https://github.com/cyssmile/openCV_learning_notes/blob/master/opencv_test/opencv_032/opencv_032.cpp
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;
void contours_info(Mat& source, vector<vector<Point>>& contours, int mod);
void contours_approxPolyDP_demo(Mat &images);
void fitEclipseDemo(Mat& images,Mat& canvas);
int main(int argc, char** arrgv)
{
Mat source1 = imread("D:/images/test11.jpg", IMREAD_COLOR);
if (source1.empty())
{
cout << "can`t open this ph" << endl;
return -1;
}
imshow("source1", source1);
contours_approxPolyDP_demo(source1);
imshow("images_demo",source1);
//椭圆轮廓拟合
Mat source2 = imread("D:/images/ellpise.jpg",-1);
if (source2.empty())
{
cout<<" not find this source "<<endl;
return -1;
}
imshow("source2",source2);
Mat canvas;
fitEclipseDemo(source2,canvas);
imshow("fiteclipse",canvas);
waitKey(0);
destroyAllWindows();
return 0;
}
void contours_info(Mat& source, vector<vector<Point>>& contours, int mod)
{
//two valued
GaussianBlur(source, source, Size(3, 3), 0);
Mat gray;
cvtColor(source, gray, COLOR_BGRA2GRAY);
Mat twoValued;
threshold(gray, twoValued, 0, 255, THRESH_BINARY | THRESH_OTSU);
bitwise_not(twoValued, twoValued);
//imshow("two_Valued", twoValued);
//find contours
vector<Vec4i> hirearchy;
findContours(twoValued, contours, hirearchy, mod, CHAIN_APPROX_SIMPLE, Point());
}
void contours_approxPolyDP_demo(Mat &images)
{
/*
* 轮廓逼近
*/
vector<vector<Point>> contours;
contours_info(images,contours,RETR_EXTERNAL);
for (size_t i =0;i<contours.size();i++)
{
Mat result;
approxPolyDP(contours[i],result,4,true);
Moments mm = moments(contours[i]);
double cx = mm.m10 / mm.m00;
double cy = mm.m01 / mm.m00;
double area = contourArea(contours[i],false);
cout << "corner:" << result.cols << " " << "Point:" << result.rows <<" "<<"area"<<area<<endl;
circle(images,Point(cx,cy),2,Scalar(0,0,255),1,8);
if (result.rows == 4)
{
putText(images,"rectangle",Point(cx,cy-10),FONT_HERSHEY_PLAIN,1.0,Scalar(0,0,255),1,8);
}
if (result.rows == 3)
{
putText(images, "tritangle", Point(cx, cy - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 1, 8);
}
if (result.rows >=5 && result.rows <= 12)
{
putText(images, "poly", Point(cx, cy - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 1, 8);
}
if (result.rows >= 13)
{
putText(images, "circle", Point(cx, cy - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 1, 8);
}
}
}
void fitEclipseDemo(Mat& images, Mat& canvas)
{
vector<vector<Point>> contours;
contours_info(images, contours, RETR_EXTERNAL);
canvas = Mat::zeros(images.size(),images.type());
canvas = Scalar::all(255);
//拟合椭圆
for (size_t i=0;i<contours.size();i++)
{
RotatedRect rrt = fitEllipse(contours[i]);
cout << rrt.size.width << " " << rrt.size.height << " " << rrt.center << endl;
ellipse(canvas,rrt,Scalar(0,0,255),1,8);
circle(canvas,rrt.center,2,Scalar(0,0,255),1,8);
}
}