1. 程式人生 > >Opencv 輪廓 逼近多邊形曲線 正外接矩形 外接最小矩形

Opencv 輪廓 逼近多邊形曲線 正外接矩形 外接最小矩形


環境 win7 + vs2015 + Opencv2.4.13

對影象輪廓點進行多邊形擬合

void approxPolyDP( InputArray curve,

                                OutputArray approxCurve,
                                double epsilon, bool closed );

InputArray curve:輸入曲線,資料型別可以為vector<Point>。

OutputArray approxCurve:輸出折線,資料型別可以為vector<Point>。

double epsilon:判斷點到相對應的line segment 的距離的閾值。(距離大於此閾值則捨棄,小於此閾值則保留,epsilon越小,折線的形狀越“接近”曲線。)

bool closed:曲線是否閉合的標誌位。

計算輪廓的垂直邊界最小矩形

Rect boundingRect( InputArray points );

計算輪廓的外接最小矩形

RotatedRect minAreaRect( InputArray points );

程式碼:

#include "opencv2/opencv.hpp"  
#include "opencv2/highgui.hpp"
#include<iostream>  
using namespace cv;
using namespace std;

RNG g_rng(12345);

Mat src;  //原圖
Mat hui;   //灰度圖
Mat erzhi;   //二值圖
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat out;   //輸出


int main(int argc, char** argv) {

	src = imread("1.jpg");
	if (!src.data) {
		cout << "No data" << endl;
		return -1;
	}

	namedWindow("原圖");
	namedWindow("輸出");
	imshow("原圖", src);

	Mat res = src.clone();

	//轉化灰度圖
	cvtColor(src, hui, CV_RGB2GRAY);  
	//高斯模糊
	GaussianBlur(hui, hui, Size(3, 3), 3, 3);  
	//腐蝕
	erode(hui, hui, element, Point(-1, -1), 1);
	//膨脹
	dilate(hui, hui, element, Point(-1, -1), 1); 

	vector<vector<Point>>cont;
	//二值化 
	threshold(hui, hui, 100, 255, THRESH_OTSU); 
	//查詢輪廓
	findContours(hui, cont, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);  

	vector<vector<Point>>contours_poly(cont.size());
	vector<Rect>boundRect(cont.size());
	vector<RotatedRect> minRect(cont.size());

	for (int i = 0; i < cont.size(); i++) {
		approxPolyDP(Mat(cont[i]), contours_poly[i], 3, true);//用指定精度逼近多邊形曲線
		boundRect[i] = boundingRect(Mat(contours_poly[i])); //外接矩形
		minRect[i] = minAreaRect(Mat(cont[i])); //最小外接矩形
	}

	for (int i = 0; i<cont.size(); i++) {
		Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
		//drawContours(res, contours_poly, i, color);
		drawContours(res, cont, i, color);

		rectangle(res, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);

		Point2f rect_points[4];
		minRect[i].points(rect_points);

		for (int j = 0; j < 4; j++) {
			line(res, rect_points[j], rect_points[(j + 1) % 4], color, 1, 8);
		}   //畫出矩形
	}

	imshow("輸出", res);

	waitKey(0);
	return 0;
}