Opencv學習筆記(二十二) 凸包檢測

凸包檢測:

凸包可以想象成一條剛好包住所有點的橡皮圈,對於二維的圖像,凸包就是將最外層的點連接起來構成凸多邊形,它能包含點集中所有的點。物體的凸包檢測常常用於物體識別、手勢識別及邊界檢測等領域。

OpenCV提供了函數convexHull()用於對物體輪廓凸包進行檢測,對形狀凸包缺陷分析時使用convexityDefects()函數,每個缺陷區包含四個特徵量:起始點,結束點,距離及最遠點。

關於函數的介紹,可以看一下OpenCV自帶的函數說明:

C++: void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true )

Parameters:
  • points – Input 2D point set, stored in std::vector or Mat.
  • hull – Output convex hull. It is either an integer vector of indices or vector of points. In the first case, the hull elements are 0-based indices of the convex hull points in the original array (since the set of convex hull points is a subset of the original point set). In the second case, hull elements aree the convex hull points themselves.
  • storage – Output memory storage in the old API (cvConvexHull2 returns a sequence containing the convex hull points or their indices).
  • clockwise – Orientation flag. If it is true, the output convex hull is oriented clockwise. Otherwise, it is oriented counter-clockwise. The usual screen coordinate system is assumed so that the origin is at the top-left corner, x axis is oriented to the right, and y axis is oriented downwards.
  • orientation – Convex hull orientation parameter in the old API, CV_CLOCKWISE or CV_COUNTERCLOCKWISE.
  • returnPoints – Operation flag. In case of a matrix, when the flag is true, the function returns convex hull points. Otherwise, it returns indices of the convex hull points. When the output array is std::vector, the flag is ignored, and the output depends on the type of the vector: std::vector<int> implies returnPoints=true, std::vector<Point> implies returnPoints=false.

發現輪廓的凸缺陷:

void convexityDefects(InputArray contours,InputArray convexhull,OutputArray convexityDefects)

完成凸包缺陷輪廓操作。參數contours表示輸入參數檢測到的輪廓,可以通過調用獲取輪廓findContours函數得到;參數convexHull函數可以vector<vector<Point>>和vector<vector<int>>兩種類型結果,凸包檢測函數convecHull應該爲vector<vector<int>>類型。參數convexityDefects爲輸出參數,檢測到的最終結果爲vector<vector<Vec4i>>類型,Vec4i存儲了起始點,結束點,距離及最遠點到凸包的距離。

凸包及缺陷檢測代碼:

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
//設置全局參數
Mat srcImage, srcGray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
void thresh_callback(int, void*)
{
	Mat srcTemp = srcImage.clone();
	Mat threMat;
	//輪廓檢測參數
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	//閾值化操作
	threshold(srcGray, threMat, thresh, 255, THRESH_BINARY);
	//輪廓檢測
	findContours(threMat, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
	//凸包及缺陷檢測參數
	vector<vector<Point> > pointHull(contours.size());
	vector<vector<int> > intHull(contours.size());
	vector<vector<Vec4i> > hullDefect(contours.size());
	for (size_t i = 0; i < contours.size(); i++)
	{
		//Point類型凸包檢測
		convexHull(Mat(contours[i]), pointHull[i], false);
		//int 類型凸包檢測
		convexHull(Mat(contours[i]), intHull[i], false);
		//凸包缺陷檢測
		convexityDefects(Mat(contours[i]), intHull[i], hullDefect[i]);
	}
	//繪製凸包及缺陷檢測
	Mat drawing = Mat::zeros(threMat.size(), CV_8UC3);
	for (size_t i = 0; i < contours.size(); i++)
	{
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point());
		drawContours(drawing, pointHull, i, color, 1, 8, vector<Vec4i>(), 0, Point());
		//繪製缺陷
		size_t count = contours[i].size();
		if (count < 300)
			continue;
		//設置凸包缺陷迭代器
		vector<Vec4i>::iterator iterDefects = hullDefect[i].begin();
		//遍歷得到4個特徵量
		while (iterDefects != hullDefect[i].end())
		{
			Vec4i& v = (*iterDefects);
			//起始位置
			int startidx = v[0];
			Point ptStart(contours[i][startidx]);
			//終止位置
			int endidx = v[1];
			Point ptEnd(contours[i][endidx]);
			//內凸殼最遠的點缺陷
			int faridx = v[2];
			Point ptFar(contours[i][faridx]);
			//凸點之間的最遠點
			int depth = v[3] / 256;
			//繪製相應的線與圓檢測結果
			if (depth > 20 && depth < 80)
			{
				line(drawing, ptStart, ptFar, CV_RGB(0, 255, 0), 2);
				line(drawing, ptEnd, ptFar, CV_RGB(0, 255, 0), 2);
				circle(drawing, ptStart, 4, Scalar(255, 0, 100), 2);
				circle(drawing, ptEnd, 4, Scalar(255, 0, 100), 2);
				circle(drawing, ptFar, 4, Scalar(100, 0, 255), 2);
			}
			iterDefects++;
		}
	}
	imshow("result", drawing);
}
int main()
{
	srcImage = imread("C:\\Users\\si\\Desktop\\1.jpg");
	if (!srcImage.data)
		return -1;
	cvtColor(srcImage, srcGray, CV_BGR2GRAY);
	blur(srcGray, srcGray, Size(3, 3));
	
	char* sour_window = "Sourse";
	namedWindow(sour_window, CV_WINDOW_AUTOSIZE);
	imshow(sour_window, srcImage);
	/*createTrackbar("Thewshold:", "Source", &thresh, max_thresh, thresh_callback);
	thresh_callback(0, 0);*/
	waitKey(0);
	return 0;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章