凸包檢測:
凸包可以想象成一條剛好包住所有點的橡皮圈,對於二維的圖像,凸包就是將最外層的點連接起來構成凸多邊形,它能包含點集中所有的點。物體的凸包檢測常常用於物體識別、手勢識別及邊界檢測等領域。
OpenCV提供了函數convexHull()用於對物體輪廓凸包進行檢測,對形狀凸包缺陷分析時使用convexityDefects()函數,每個缺陷區包含四個特徵量:起始點,結束點,距離及最遠點。
關於函數的介紹,可以看一下OpenCV自帶的函數說明:
C++: void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true )
Parameters: |
|
---|
發現輪廓的凸缺陷:
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;
}
|
|
---|