因为我们在进行虚拟键盘的设定的时候,需要利用摄像头对手指进行拍摄,确定手指当前的位置,然后进行键盘输入内容的估计,所以采用了以下方法:
方法一:重心距离法
见下图,红色点是手的重心,那么手的边缘的所有点与重心点的距离按顺时针方向或者逆时针方向遍历,就会出现五个峰值,分别是五个手指,这样我们就可以简单找到了。如果你是只伸出一两个手指,那么就只有一两个峰值了。
简单的代码如下:
1、对图像做高斯模糊;
2、肤色分割(背景不要有类肤色,如果有,就需要加其他信息来排除干扰);
3、找到手轮廓;
4、计算矩,即重心;
5、寻找指尖。
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
void skinExtract(const Mat &frame, Mat &skinArea);
int main(int argc, char* argv[])
{
Mat frame, skinArea;
VideoCapture capture;
capture.open(0);
if (!capture.isOpened())
{
cout<<"No camera!\n"<<endl;
return -1;
}
while (1)
{
capture >> frame;
//Mat frame = imread("fingertips(1).jpg");
if (frame.empty())
break;
skinArea.create(frame.rows, frame.cols, CV_8UC1);
skinExtract(frame, skinArea);
Mat show_img;
frame.copyTo(show_img, skinArea);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
//寻找轮廓
findContours(skinArea, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
// 找到最大的轮廓
int index;
double area, maxArea(0);
for (int i=0; i < contours.size(); i++)
{
area = contourArea(Mat(contours[i]));
if (area > maxArea)
{
maxArea = area;
index = i;
}
}
//drawContours(frame, contours, index, Scalar(0, 0, 255), 2, 8, hierarchy );
Moments mom