我使用下面的代码来检测手并在其中绘制一个凸包。
以下是我的代码流程:
1)角点检测(阈值)。
2)腐蚀+膨胀。
3)轮廓检测。
4)最大轮廓的凸包。
5)凸性。
6)Countour + Hull绘制轮廓。
#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 src; Mat src_gray;
int thresh = 147;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void thresh_callback(int, void* );
/** @function main */
int main( int argc, char** argv )
{
// src = imread( "D:\\Projects\\Proposals\\Knuckle_Detection\\images\\picture028.jpg", 1 );
VideoCapture cap(0);
while(1)
{
cap>>src;
/// Convert image to gray and blur it
resize(src,src,Size(640,480),0,0,INTER_LINEAR);
cvtColor( src, src_gray, CV_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
/// Create Window
char* source_window = "Knuckle Extractor";
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
thresh_callback( 0, 0 );
waitKey(5);
}
return(0);
}
/** @function thresh_callback */
void thresh_callback(int, void* )
{
Mat src_copy = src.clone();
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY||CV_THRESH_OTSU );
imshow("b/f threshold", threshold_output);
erode(threshold_output,threshold_output,Mat ());
dilate(threshold_output,threshold_output,Mat ());
imshow("Threshold",threshold_output);
findContours( threshold_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Find the convex hull object for each contour
vector<vector<Point > >hull( contours.size() );
vector<vector<Vec4i> >defects( contours.size() );
vector<vector<int > >hull1( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{
convexHull( Mat(contours[i]), hull[i], false );
convexHull( Mat(contours[i]), hull1[i], false );
}
for( int i = 0; i < contours.size(); i++ )
{
//convexHull( Mat(contours[i]), hull[i], false );
if (contours[i].size() >3 )
{
convexityDefects(contours[i], hull1[i], defects[i]);
cout<<"inside"<<endl;
}
}
/// Draw contours + hull results
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(10, 10), rng.uniform(0,255), rng.uniform(0,10) );
drawContours( src, contours, i, color, 5, 8, vector<Vec4i>(), 0, Point() );
drawContours( src, hull, i, color, 5, 8, vector<Vec4i>(), 0, Point() );
cout<<"in"<<endl;
cout<<"out"<<endl;
}
/// Show in a window
namedWindow( "Result", CV_WINDOW_AUTOSIZE );
imshow( "Result", src );
}
以下是代码的输出。
我的目的是从我得到的上述输出中提取红色标记的区域。可以获得一些想法或代码片段,如下所示。
我还添加了原始图像供人们分析。
更新
我使用了高斯混合模型并获得了以下输出。
我还应用了Canny edge来获取图像上的“边缘”,下面是输出。
是否有可能仅提取具有上述两个输出的关节部分? “goodFeaturesToTrack”会帮助我吗?