扩展库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;
}
}

  

基本例程(4-1)手势识别C++ 和简单形状匹配的更多相关文章

  1. leetcode 10 Regular Expression Matching(简单正则表达式匹配)

    最近代码写的少了,而leetcode一直想做一个python,c/c++解题报告的专题,c/c++一直是我非常喜欢的,c语言编程练习的重要性体现在linux内核编程以及一些大公司算法上机的要求,pyt ...

  2. hdu-4185.loiol_skimming(简单二分匹配模型)

    /************************************************************************* > File Name: hdu-4185. ...

  3. POJ2446 模板盖格子 简单二分匹配

    题意:       给你一个n*m的格子,有的格子上有坑,然后让你用1*2的东西去覆盖所有没有坑的格子,不能重叠,坑上也不能放东西覆盖,问是否能成功. 思路:        简单题目,每个格子和四周的 ...

  4. POJ2239简单二分匹配

    题意:       一周有7天,每天可以上12节课,现在给你每科课的上课时间,问你一周最多可以上几科课,一科课只要上一节就行了. 思路:       简单题目,直接二分就行了,好久没写二分匹配了,练习 ...

  5. 简单正则匹配QQ邮箱

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <script src ...

  6. js小例子(简单模糊匹配输入信息)

    该例子实现的是用户输入信息或者字母时可以搜索出来,鼠标点击选择 <!DOCTYPE html> <html> <style> p{ width:200px; hei ...

  7. Dolls - 4160(简单二分图匹配)

    题意:有一些箱子,大箱子可以套小箱子,但是必须h>h,w>w,l>l,求出来最外面能剩下几个箱子无法被嵌套.   分析:思考每个箱子都只会被别的箱子套一次,所以构成一二分匹配模型,只 ...

  8. E - Swap - hdu 2819(简单二分图匹配)

    题意:如果可以交换行列,问主对角线能不能全为1 分析:要想主对角线全为1很明显要有N个行列不想同的点就行了,可以用二分图匹配计算出来多能有几个.如果小与N就不能.输出要是对的就行,不必和答案一样 ** ...

  9. C#中一个简单的匹配16进制颜色的正则测试

    using System; using System.Text.RegularExpressions; namespace Test { class Program { //匹配16进制颜色代码的正则 ...

随机推荐

  1. Golang读取并修改非主流配置文件

    今天工作中碰到的问题,要求修改此配置文件,没看出来是什么格式,用了下面的思路: mysql { # If any of the files below are set, TLS encryption ...

  2. - XML 解析 总结 DOM SAX PULL MD

    目录 目录 XML 解析 总结 DOM SAX PULL MD 几种解析方式简介 要解析的内容 DOM 解析 代码 输出 SAX 解析 代码 输出 JDOM 解析 代码 输出 DOM4J 解析 代码 ...

  3. 创建一个dotnetcore的SPA模板项目

    MPA和SPA 对比 dotnet new --install Microsoft.AspNetCore.SpaTemplates::* 我这边用的是vue dotnet new vue dotnet ...

  4. 深入理解TCP/IP传输层

    传输层:负责数据能够从发送端传到接收端(只需要关注点对点的传输,中间的传输过程一概不管) UDP和TCP UDP(全双工):1.无连接,2不可靠,3.面向数据报 分别表示UDP源端口号.目的端口号.U ...

  5. Java 之 可变字符序列:字符串缓冲区(StringBuilder 与 StringBuffer)

    一.字符串拼接问题 由于 String 类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象. Demo: public class StringDemo { public ...

  6. 号称全站最直观解释-smv核函数-是干啥

    认识 svm 在求解时, 通过某非线性变换 φ( x) ,将输入空间映射到高维特征空间.特征空间的维数可能非常高.如果支持向量机的求解只用到内积运算,而在低维输入空间又存在某个函数 K(x, x′) ...

  7. 2015年br运维操作归档

    归档2015年在br做运维时常用的命令,主要梳理出log的过滤操作. 对于日志文本的处理,常见还是sed和awk,具体如下: 统计ip访问量: cat nginx.log |awk '{print $ ...

  8. Redis SCAN命令实现有限保证的原理

    SCAN命令可以为用户保证:从完整遍历开始直到完整遍历结束期间,一直存在于数据集内的所有元素都会被完整遍历返回,但是同一个元素可能会被返回多次.如果一个元素是在迭代过程中被添加到数据集的,又或者是在迭 ...

  9. Virtualbox 设置虚拟机和物理机共享文件夹

    Virtualbox 设置虚拟机和物理机共享文件夹 概述 当我们在本地机安装好一个虚拟机后,特别是安装linux系统的朋友们,经常需要将本地机的文件传递到虚拟机中, 能实现的方式肯定是多式多样的,就本 ...

  10. 详解CentOS6.7部署Tomcat及主配置文件

    Java程序实现部署及应用 POSIX :可移植操作系统,编程操作系统接口规范,实现跨平台编译运行. API:应用程序编程接口 ABI:应用程序二进制接口 描述了应用程序和操作系统之间,一个应用和它的 ...