opencv怎么找到手指最高处

47 篇文章 2 订阅
24 篇文章 1 订阅

目录

一、目的:

1、最近要做一个Unity中显示相机画面中手指的最高点,然后有蝴蝶飞上去的项目,所以涉及到了OpenCV在Unity中的使用+OpenCV获取手指的最高点等等 

一、参考:

1、如何利用opencv的库测量手指长度 [问题点数:20分]:

①总结:pass:只说了思想,没有实现的方法,

2、opencv实现简单手指位置识别

①总结:good:有实现方法,能借鉴,将原本代码稍微修改了一下,运行效果如下:

3、基于 OpenCv 和 Python 的手指识别及追踪

①总结:pass:没有实现的方法,

4、opencv 手势识别

①总结:pass:没有实现的方法,

5、OpenCV+python手势识别框架和实例讲解

①总结:待整理

6、python-opencv2利用cv2.findContours()函数来查找检测物体的轮廓

①总结:pass:python写的,暂时在c++中实现不了

7、OpenCV FindContours使用

①总结:good:第一个、第二个运行效果如下图,可以参考:

8、关于findContours的一些知识点

①总结:pass:自己复制下来后运行到一些地方就会直接报错,无法执行下去

9、OpenCV3之——查找并绘制轮廓findContours()和drawContours()

①总结:good:可以实现,值得参考,总共2个程序,运行如下图:

10、OpenCV简单粗糙的指尖检测方法(FingerTips Detection)

①总结:pass:代码执行不了,很乱

11、使用opencv提取手部信息

①总结:good:代码1、代码2、修改后运行摄像头的运行效果如下图:

12、手势检测及手掌质心的运动轨迹(opencv)

①总结:good:代码按照截图抄下来,运行如下、抄写的代码如下;but:有时候运行一段时间会出现vector超出数组长度

13、OpenCV简单粗糙的指尖检测方法(FingerTips Detection)

①总结:good:代码能够直接运行,代码1+代码2运行如下图;but:背景不要有类肤色,如果有,就需要加其他信息来排除干扰

14、用opencv检测convexity defects

①总结:good:运行结果如下,需要将图片保存下来,路径修改一下;but:曾经将其修改为相机的,但是受周围环境的影响太大了:

15、基于OpenCVSharp的图像处理软件

①总结:good;了解了有C#封装好的OpenCV;

16、在C#中使用OpenCV(使用OpenCVSharp)

①总结:good:了解有C#封装好的OpenCV;

17、Unity使用OpenCvSharp人脸识别

①总结:good:下载的工程运行效果如下图:打开相机+识别相机画面中的人脸;but:发布到了安卓手机上面,发现和电脑端不一样,点击按钮没有反应,只有相机画面

 


 

一、目的:

1、最近要做一个Unity中显示相机画面中手指的最高点,然后有蝴蝶飞上去的项目,所以涉及到了OpenCV在Unity中的使用+OpenCV获取手指的最高点等等 

一、参考:

1、如何利用opencv的库测量手指长度 [问题点数:20分]:

https://bbs.csdn.net/topics/392569485

①总结:pass:只说了思想,没有实现的方法,

2、opencv实现简单手指位置识别

https://blog.csdn.net/u013294888/article/details/73477734

①总结:good:有实现方法,能借鉴,将原本代码稍微修改了一下,运行效果如下:

// FingerRecognition.cpp : 定义控制台应用程序的入口点。
//

//
//整体思路:
//
//1.过滤噪声
//
//2.由于RGB颜色的离散性转换为HSV通道
//
//3.对HSV空间进行量化,得到2值图像,亮的部分为手的形状
//
//4.去除杂点造成的伪轮廓,留下手的真实轮廓
//
//5.对凸出点连线
//
//6.最高点到底部中点的连线即为手指方向
//
部分代码:
//将MFC实现部分给省略了,给出了完整的opencv部分代码,可以参考实现。
#include "stdafx.h"
#include "stdlib.h"
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	cv::VideoCapture cap(0);
	if (!cap.isOpened())
	{
		return -1;
	}
	//
	cv::Mat frame;
	cv::Mat frameHSV;
	//
	std::vector< std::vector<cv::Point> > OriginalContours;//轮廓
	std::vector< cv::Vec4i > hierarchy; // 轮廓的结构信息
										//
	std::vector< std::vector<cv::Point> > FinalContours;// 筛选后的轮廓
	std::vector< cv::Point > hull;  // 凸包络的点集
									//
	//CString Str;
	string Str;
	int i, j;
	int Width = cap.get(CV_CAP_PROP_FRAME_WIDTH), Height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
	float fHeight = ((float)2 / 3 - (float)1 / 7) * Height;
	//
	//while (0 == pDlg->m_bStopFlag)
	while (1)
	{
		cap >> frame;
		if (frame.empty())
		{
			break;
		}
		//左右翻转
		cv::flip(frame, frame, 1);
		//中值滤波,用了这个下面的其他滤波全部异常
		//medianBlur(frame, frame, 10);
		//高斯滤波
		cv::GaussianBlur(frame, frame, cv::Size(7, 7), 1.5, 1.5);
		//通道转换
		cv::cvtColor(frame, frameHSV, CV_BGR2HSV);
		//imshow("frameHSV", frameHSV);
		/*
		S = 符号整型  U = 无符号整型  F = 浮点型
		E.g.:
		CV_8UC1 是指一个8位无符号整型单通道矩阵,
		CV_32FC2是指一个32位浮点型双通道矩阵
		CV_8UC1          CV_8SC1          CV_16U C1       CV_16SC1
		CV_8UC2          CV_8SC2          CV_16UC2        CV_16SC2
		CV_8UC3          CV_8SC3          CV_16UC3        CV_16SC3
		CV_8UC4          CV_8SC4          CV_16UC4        CV_16SC4
		CV_32SC1         CV_32FC1         CV_64FC1
		CV_32SC2         CV_32FC2         CV_64FC2
		CV_32SC3         CV_32FC3         CV_64FC3
		CV_32SC4         CV_32FC4         CV_64FC4
		*/
		// 对HSV空间进行量化,得到2值图像,亮的部分为手的形状
		cv::Mat mask(frame.rows, frame.cols, CV_8UC1);
		//inRange(frameHSV, cv::Scalar(0, 30, 30), cv::Scalar(40, 170, 256), mask);
		inRange(frameHSV, cv::Scalar(5, 30, 30), cv::Scalar(40, 170, 256), mask);
		//
		// 腐蚀:去除小亮点 膨胀:连接区块
		cv::erode(mask, mask, cv::Mat(5, 5, CV_8U), cv::Point(-1, -1), 1);
		//cv::dilate(mask, mask, cv::Mat(5, 5, CV_8U), cv::Point(-1, -1), 2);
		//imshow("frameHSV", frameHSV);
		//imshow("mask", mask);
		OriginalContours.clear();
		hierarchy.clear();
		FinalContours.clear();
		// 得到手的轮廓
		cv::findContours(mask, OriginalContours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
		// 去除伪轮廓
		for (i = 0; i < OriginalContours.size(); i++)
		{
			if (fabs(cv::contourArea(cv::Mat(OriginalContours[i]))) > 25000)
			{
				FinalContours.push_back(OriginalContours[i]);
			}
		}
		// 画轮廓
		cv::drawContours(frame, FinalContours, -1, cv::Scalar(0, 0, 255), 3);
		// 得到轮廓的凸包络
		int hullcount;
		int iNumOfContours = FinalContours.size();
		cv::Point top;
		for (j = 0; j < iNumOfContours; j++)
		{
			convexHull(cv::Mat(FinalContours[j]), hull, true);
			hullcount = (int)hull.size();
			//
			for (i = 0; i<hullcount - 1; i++)
			{
				cv::line(frame, hull[i + 1], hull[i], cv::Scalar(255, 0, 0), 2, CV_AA);
			}
			cv::line(frame, hull[hullcount - 1], hull[0], cv::Scalar(255, 0, 0), 2, CV_AA);
			//画点
		//	GetTopPoint(hull, hullcount, top);
			cv::line(frame, top, top, cv::Scalar(255, 0, 255), 18, CV_AA);
			cv::line(frame, top, cv::Point(Width / 2, Height), cv::Scalar(0, 255, 255), 2, CV_AA);
			//
			if (1 == iNumOfContours)
			{
				//pDlg->m_FingerPosition.bChanged = 1;
				//pDlg->m_FingerPosition.top = ((float)top.y - (float)Height / 7) / fHeight;
				//pDlg->m_FingerPosition.left = (float)top.x / (float)Width;
			}
		}
		//
		cv::line(frame, cv::Point(0, Height / 7), cv::Point(Width, Height / 7), cv::Scalar(255, 255, 255), 2, CV_AA);
		cv::line(frame, cv::Point(0, 2 * Height / 3), cv::Point(Width, 2 * Height / 3), cv::Scalar(255, 255, 255), 2, CV_AA);
		imshow("frame", frame);
		cv::waitKey(33);
	}
	return 0;
}

3、基于 OpenCv 和 Python 的手指识别及追踪

https://www.leiphone.com/news/201808/hWpuSivLzkKrqSCs.html

①总结:pass:没有实现的方法,

4、opencv 手势识别

https://www.cnblogs.com/snake-hand/p/3187044.html

①总结:pass:没有实现的方法,

5、OpenCV+python手势识别框架和实例讲解

https://www.jb51.net/article/144995.htm

①总结:待整理

6、python-opencv2利用cv2.findContours()函数来查找检测物体的轮廓

https://blog.csdn.net/hjxu2016/article/details/77833336

①总结:pass:python写的,暂时在c++中实现不了

7、OpenCV FindContours使用

https://blog.csdn.net/ktigerhero3/article/details/88314729

①总结:good:第一个、第二个运行效果如下图,可以参考:

8、关于findContours的一些知识点

https://blog.csdn.net/m0_37350758/article/details/82016820

①总结:pass:自己复制下来后运行到一些地方就会直接报错,无法执行下去

9、OpenCV3之——查找并绘制轮廓findContours()和drawContours()

https://blog.csdn.net/qq_35294564/article/details/82947011

①总结:good:可以实现,值得参考,总共2个程序,运行如下图:

10、OpenCV简单粗糙的指尖检测方法(FingerTips Detection)

https://blog.csdn.net/ytffhew/article/details/84076849

①总结:pass:代码执行不了,很乱

11、使用opencv提取手部信息

https://blog.csdn.net/zhyh1435589631/article/details/53293211

①总结:good:代码1、代码2、修改后运行摄像头的运行效果如下图:

12、手势检测及手掌质心的运动轨迹(opencv)

https://blog.csdn.net/logan_lin/article/details/79517571

①总结:good:代码按照截图抄下来,运行如下、抄写的代码如下;but:有时候运行一段时间会出现vector超出数组长度

//成功:显示视频中手势
//参考:https://blog.csdn.net/logan_lin/article/details/79517571

#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

Point Ycrcb_Otsu_detect(Mat & src);
Point image_centrt(Mat& src, vector<vector<Point>>&filterContours, Mat&output_mask);

int main()
{
	VideoCapture cap;
	cap.open(0);
	if (!cap.isOpened())
	{
		cout << "相机没有打开!"<<endl;
		return -1;
	}
	Mat frame;
	Mat HSV;
	Mat Ycrcb;
	Point center;
	vector<Point> center_all;
	while (1)
	{
		cap >> frame;

		center = Ycrcb_Otsu_detect(frame);
		center_all.push_back(center);
		if (center_all.size()!=1)
		{
			for (int i=0;i<center_all.size()-1;i++)
			{
				line(frame, center_all[i], center_all[i + 1], Scalar(128, 255, 128), 2);
			}
		}
		imshow("frame", frame);
		waitKey(100);
	}


	return 0;
}

Point Ycrcb_Otsu_detect(Mat & src)
{
	Mat ycrcb_image;
	GaussianBlur(src, src, Size(7, 7), 3, 3);
	cvtColor(src, ycrcb_image, CV_BGR2YCrCb);
	Mat detect;
	vector <Mat> channels;
	split(ycrcb_image, channels);
	Mat output_mask = channels[1];
	threshold(output_mask, output_mask, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
	src.copyTo(detect, output_mask);
	imshow("Ycrcb_output_mask", output_mask);

	vector<vector<Point>> contours;
	vector<vector<Point>> filterContours;
	vector<Vec4i> hierarchy;
	findContours(output_mask, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
	int index;
	for (int i=0;i<contours.size();i++)
	{
		int square = fabs(contourArea(Mat(contours[i])));
		if (fabs(contourArea(Mat(contours[i])))>100&&fabs((contourArea(Mat(contours[i])))>10000))				//数字根据实际情况调整
		{
			filterContours.push_back(contours[i]);
			index = i;
		}
	}
	drawContours(src, filterContours, -1, Scalar(0, 255, 255), 3);

	Point center;
	center = image_centrt(src, filterContours, output_mask);

	return center;
}

Point image_centrt(Mat& src, vector<vector<Point>>&filterContours, Mat&output_mask)
{
	Point center;
	if (filterContours.size()!=0)
	{
		Moments moment = moments(output_mask, true);												//求取质心
		center = Point(moment.m10 / moment.m00, moment.m01 / moment.m00);
		circle(src, center, 5, Scalar(0, 0, 255), CV_FILLED);
		vector<Point> hull;
		vector<int> hull_i;

		vector<Vec4i> defect;
		for (int i=0;i<filterContours.size();i++)
		{
			convexHull(Mat(filterContours[i]), hull, true);
			convexHull(Mat(filterContours[i]), hull_i, false);

			convexityDefects(Mat(filterContours[i]), hull_i, defect);
			int hullcount = (int)hull.size();
			for (int j=0;j<hullcount-1;j++)
			{
				circle(src, hull[j], 3, Scalar(255, 0, 0), CV_FILLED);

			}
			vector<Vec4i>::iterator d = defect.begin();
			while (d != defect.end())
			{
				Vec4i& v = (*d);
				int startidex = v[0];
				Point ptStart(filterContours[i][startidex]);					//一堆凸包中的第一个点
				int endidx = v[i];
				Point ptEnd(filterContours[i][endidx]);						//一堆凸包中的最后以恶搞点
				int faridx = v[2];
				Point ptFar(filterContours[i][faridx]);							//凹点
				int depth = v[3] / 256;													//凹点和凸点的距离									
				if (depth>20&&depth<140)
				{
					line(src, ptStart, ptFar, CV_RGB(0, 255, 0), 2);
					line(src, ptEnd, ptFar, CV_RGB(0, 255, 0), 2);
					circle(src, ptStart, 4, Scalar(255, 0, 100), 2);
					circle(src, ptEnd, 4, Scalar(255, 0, 100), 2);
					circle(src, ptFar, 4, Scalar(100, 0, 255), 2);
				}
				d++;
			}
		}
	}
	return center;
}

13、OpenCV简单粗糙的指尖检测方法(FingerTips Detection)

https://blog.csdn.net/augusdi/article/details/8865589

①总结:good:代码能够直接运行,代码1+代码2运行如下图;but:背景不要有类肤色,如果有,就需要加其他信息来排除干扰

14、用opencv检测convexity defects

http://blog.csdn.net/lichengyu/article/details/38392473

①总结:good:运行结果如下,需要将图片保存下来,路径修改一下;but:曾经将其修改为相机的,但是受周围环境的影响太大了:

15、基于OpenCVSharp的图像处理软件

https://blog.csdn.net/you_big_father/article/details/86088531

①总结:good;了解了有C#封装好的OpenCV;

16、在C#中使用OpenCV(使用OpenCVSharp)

https://www.cnblogs.com/jsxyhelu/p/9669583.html

①总结:good:了解有C#封装好的OpenCV;

17、Unity使用OpenCvSharp人脸识别

https://blog.csdn.net/AWNUXCVBN/article/details/51629404

①总结:good:下载的工程运行效果如下图:打开相机+识别相机画面中的人脸;but:发布到了安卓手机上面,发现和电脑端不一样,点击按钮没有反应,只有相机画面

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值