轮廓逼近与拟合

轮廓逼近

本节相关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);
	}
}
posted @ 2020-03-29 14:50  cyssmile  阅读(597)  评论(0编辑  收藏  举报