zoukankan      html  css  js  c++  java
  • 基本例程(4-1)手势识别C++ 和简单形状匹配

    扩展库https://blog.csdn.net/Taily_Duan/article/details/52130135

     opencv3.3+扩展库

    /************************************************************************/
    /*
    Description:	手势检测
    先滤波去噪
    -->转换到HSV空间
    -->根据皮肤在HSV空间的分布做出阈值判断,这里用到了inRange函数,
    然后进行一下形态学的操作,去除噪声干扰,是手的边界更加清晰平滑
    -->得到的2值图像后用findContours找出手的轮廓,去除伪轮廓后,再用convexHull函数得到凸包络
    Author:			Yang Xian
    History:
    */
    /************************************************************************/
    #include <iostream>	// for standard I/O
    #include <string>   // for strings
    #include <iomanip>  // for controlling float print precision
    #include <sstream>  // string to number conversion
    
    #include <opencv2/imgproc/imgproc.hpp>  // Gaussian Blur
    #include <opencv2/core/core.hpp>        // Basic OpenCV structures (cv::Mat, Scalar)
    #include <opencv2/highgui/highgui.hpp>  // OpenCV window I/O
    
    using namespace cv;
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	const std::string sourceReference = "test3.avi";
    	int delay = 1;
    
    	char c;
    	int frameNum = -1;			// Frame counter
    
    	//VideoCapture captRefrnc(sourceReference);
    	VideoCapture captRefrnc(0);
    
    
    	if (!captRefrnc.isOpened())
    	{
    		// 		cout  << "Could not open reference " << sourceReference << endl;
    		return -1;
    	}
    
    	Size refS = Size((int)captRefrnc.get(CV_CAP_PROP_FRAME_WIDTH),
    		(int)captRefrnc.get(CV_CAP_PROP_FRAME_HEIGHT));
    
    	bool bHandFlag = false;
    
    	const char* WIN_SRC = "Source";
    	const char* WIN_RESULT = "Result";
    
    	// Windows
    	namedWindow(WIN_SRC, CV_WINDOW_AUTOSIZE);
    	namedWindow(WIN_RESULT, CV_WINDOW_AUTOSIZE);
    
    	Mat frame;	// 输入视频帧序列
    	Mat frameHSV;	// hsv空间
    	Mat mask(frame.rows, frame.cols, CV_8UC1);	// 2值掩膜
    	Mat dst(frame);	// 输出图像
    
    					// 	Mat frameSplit[4];
    
    	vector< vector<Point> > contours;	// 轮廓
    	vector< vector<Point> > filterContours;	// 筛选后的轮廓
    	vector< Vec4i > hierarchy;	// 轮廓的结构信息
    	vector< Point > hull;	// 凸包络的点集
    
    	while (true) //Show the image captured in the window and repeat
    	{
    		captRefrnc >> frame;
    
    		if (frame.empty())
    		{
    			cout << " < < <  Game over!  > > > ";
    			break;
    		}
    		imshow(WIN_SRC, frame);
    
    		// Begin
    
    		// 中值滤波,去除椒盐噪声
    		medianBlur(frame, frame, 5);
    		// 		GaussianBlur( frame, frameHSV, Size(9, 9), 2, 2 );
    		// 		imshow("blur2", frameHSV);
    		//		pyrMeanShiftFiltering(frame, frameHSV, 10, 10);
    		//	 	imshow(WIN_BLUR, frameHSV);
    		// 转换到HSV颜色空间,更容易处理
    		cvtColor(frame, frameHSV, CV_BGR2HSV);
    
    		// 		split(frameHSV, frameSplit);
    		// 		imshow(WIN_H, frameSplit[0]);
    		// 		imshow(WIN_S, frameSplit[1]);
    		// 		imshow(WIN_V, frameSplit[2]);
    
    		Mat dstTemp1(frame.rows, frame.cols, CV_8UC1);
    		Mat dstTemp2(frame.rows, frame.cols, CV_8UC1);
    		// 对HSV空间进行量化,得到2值图像,亮的部分为手的形状
    		inRange(frameHSV, Scalar(0, 30, 30), Scalar(40, 170, 256), dstTemp1);
    		inRange(frameHSV, Scalar(156, 30, 30), Scalar(180, 170, 256), dstTemp2);
    		bitwise_or(dstTemp1, dstTemp2, mask);
    		// 		inRange(frameHSV, Scalar(0,30,30), Scalar(180,170,256), dst);		
    
    		// 形态学操作,去除噪声,并使手的边界更加清晰
    		Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
    		erode(mask, mask, element);
    		morphologyEx(mask, mask, MORPH_OPEN, element);
    		dilate(mask, mask, element);
    		morphologyEx(mask, mask, MORPH_CLOSE, element);
    
    		frame.copyTo(dst, mask);
    
    		contours.clear();
    		hierarchy.clear();
    		filterContours.clear();
    		// 得到手的轮廓
    		findContours(mask, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    		// 去除伪轮廓
    		for (size_t i = 0; i < contours.size(); i++)
    		{
    			// 			approxPolyDP(Mat(contours[i]), Mat(approxContours[i]), arcLength(Mat(contours[i]), true)*0.02, true);
    			if (fabs(contourArea(Mat(contours[i]))) > 30000)	//判断手进入区域的阈值
    			{
    				filterContours.push_back(contours[i]);
    			}
    		}
    		// 画轮廓
    		drawContours(dst, filterContours, -1, Scalar(0, 0, 255), 3/*, 8, hierarchy*/);
    		// 得到轮廓的凸包络
    		for (size_t j = 0; j<filterContours.size(); j++)
    		{
    			convexHull(Mat(filterContours[j]), hull, true);
    			int hullcount = (int)hull.size();
    
    			for (int i = 0; i<hullcount - 1; i++)
    			{
    				line(dst, hull[i + 1], hull[i], Scalar(255, 0, 0), 2, CV_AA);
    			}
    			line(dst, hull[hullcount - 1], hull[0], Scalar(255, 0, 0), 2, CV_AA);
    		}
    
    		imshow(WIN_RESULT, dst);
    		dst.release();
    		// End
    
    		c = cvWaitKey(delay);
    		if (c == 27) break;
    	}
    }
    

      

  • 相关阅读:
    为什么不应该使用ZooKeeper做服务发现
    Python 练习 人事管理
    Python 爬取 妹子图(技术是无罪的)
    Python 爬取 书籍
    Python 爬取 豆瓣
    Python 爬取 房天下
    Python 爬取 煎蛋
    Python 爬取 拉钩
    Python 爬取 猫眼
    家具专区网
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/11079943.html
Copyright © 2011-2022 走看看