基本例程(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;
	}
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM