3D手势识别(一)顺/逆时针画圈判断

2024-02-20 08:30

本文主要是介绍3D手势识别(一)顺/逆时针画圈判断,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

场景:前装摄像头

检测动作:单手指画圈,需要判断画圈方向和圈数。

     

步骤: (1)取得3D图像序列最前点;

            (2)将最前点投影在2D平面上;

            (3)中值滤波和平滑处理;

            (4)得到2D点集进行线性插值;

            (5)以重心为中心判断是否闭环;

            (6)2D点集进行椭圆拟合,判断是否椭圆、椭圆半径和椭圆度范围;

    (7)  2D点集进行圆拟合,计算半径均值和标准差;

            (8)判断2D点集方向:顺/逆时针。

其中手的识别使用深度学习进行,根据TensorFlow训练完的模型判断出图像中有手且为单手指,
去掉背景、挖出只含有手的图像;中值滤波用的OpenCV medianBlur函数,其他主要函数算法如下:


Table of Contents

1、2D点集线性插值算法

2、计算重心

3、闭环判断

4、椭圆拟合

5、圆拟合

6、顺/逆时针方向判断


1、2D点集线性插值算法

//************************************
// Description: 插值,根据两点间距离线性插值,两点间距离越大插值越多,距离小于min_dis则不插值返回原值
// Method:    InterpCurve
// FullName:  InterpCurve
// Access:    private
// Parameter: 插值前二维点集 std::vector<cv::Point2f> &data
// Parameter: 插值后二维点集 std::vector<cv::Point2f> &result
// Parameter: 最小插值距离 float min_dis
// Returns:
// Author:    
// Date:      2018/08/28
// History:
//************************************
void InterpCurve(std::vector<cv::Point2f> &data, std::vector<cv::Point2f> &result, float min_dis) {result.clear();result.reserve(data.size());result.push_back(data.at(0));for (size_t i = 1; i < data.size(); i++) {float dis = Distance(data.at(i - 1), data.at(i));float num = dis / min_dis + 1;float step = 1.0f / num;float s = 0;while (s <= 1.0) {result.emplace_back(cv::Point2f((1 - s) * data.at(i - 1).x + s * data.at(i).x,(1.0f - s) * data.at(i - 1).y + s * data.at(i).y));s += step;}}//  vecp::print(result, "result");
}

2、计算重心

3D点计算方法类似。

//************************************
// Description: 将输入的point2d点集求和平均求重心
// Method:    CalcCentre
// FullName:  CalcCentre
// Access:    private
// Parameter: 二维点集 const std::vector<cv::Point2f> &point2ds
// Returns:   重心坐标 cv::Point2f
// Author:    
// Date:      2018/08/28
// History:
//************************************
cv::Point2f CalcCentre(const std::vector<cv::Point2f> &point2ds) {float x = 0, y = 0;for (auto &pt: point2ds) {x += pt.x;y += pt.y;}return cv::Point2f(x / point2ds.size(), y / point2ds.size());
}

3、闭环判断

//************************************
// Description: 将输入的point2d点集判断是否闭环
// Method:    FindOneCircleFromUnformInCircle
// FullName:  FindOneCircleFromUnformInCircle
// Access:    private
// Parameter: 二维点集 const std::vector<cv::Point2f> &point2ds
// Parameter: 判断闭环坐标中心 const cv::Point2f &centre
// Parameter: 最大无点角度0-360 float max_angle
// Parameter: 划分区域数量 int part_count
// Returns:   bool
// Author:    
// Date:      2018/08/28
// History:
//************************************
bool FindOneCircleFromUnformInCircle(const std::vector<cv::Point2f> &point2ds,const cv::Point2f &centre,float max_angle, int part_count) {double each_path_dog = 2.0f * M_PI / part_count;//cout<<"each_path_dog:"<<each_path_dog<<"  ";std::vector<int> counts(part_count, 0);int full_part_counts = 0;for (auto &pt: point2ds) {float alpha = atan2Ex(pt.x - centre.x, pt.y - centre.y);auto idx = static_cast<size_t>(alpha / each_path_dog);counts.at(idx)++;}//每个区域大于5个点算作填满for (auto &count: counts) {if (count > 5)full_part_counts++;}double dao_each_path_dog = 1.0 / each_path_dog;//填满区域大于需要填满的区域则返回truereturn full_part_counts  >= int(DegToRad(360.0 - max_angle) * dao_each_path_dog);
}

4、椭圆拟合

使用了OpenCV的fitEllipseEx函数。

//************************************
// Description: 将输入的point2d点集做椭圆拟合
// Method:    IsCircleFromEllipse
// FullName:  IsCircleFromEllipse
// Access:    private
// Parameter: 二维点集 const std::vector<cv::Point2f> &point2ds
// Parameter: 最小半径 float min_radius
// Parameter: 最大椭圆度(两半径比值) float min_ovality
// Parameter: 最大非拟合点 float min_error
// Returns:   bool
// Author:    
// Date:      2018/08/28
// History:
//************************************
bool IsCircleFromEllipse(const std::vector<cv::Point2f> &point2ds,float min_radius, float min_ovality, float min_error,cv::RotatedRect &ellipse) {//OpenCV椭圆拟合,要求至少有六个点输入float error = fitEllipseEx(point2ds, ellipse);float a = ellipse.size.width;float b = ellipse.size.height;//printf("a %f, b %f, ovality %f, error %f\n", a, b, a/b, error);return !(a < min_radius || b < min_radius || a / b < min_ovality || a / b > 1.0 / min_ovality ||error > min_error);
}

5、圆拟合

以重心为圆心设置半径均值和标准差阈值:

 /************************************Description: 将输入的point2d点集做圆拟合,根据圆心计算半径均值和标准差Method:    IsCircelFromDevFullName:  IsCircelFromDevAccess:    privateParameter: 最小半径均值 float min_radiusParameter: 最大半径标准差 float max_devReturns:   boolAuthor:    Date:      2018/10/17History:
************************************/
bool CircleAction::IsCircelFromDev(const std::vector<cv::Point2f> &point2ds, float min_radius, float max_dev) {cv::Point2f centre = CalcCentre(point2ds);std::vector<float> radius(point2ds.size(), 0.0f);for (size_t i = 0; i < point2ds.size(); i++) {radius.at(i) = Distance(centre, point2ds.at(i));}cv::Mat mean, dev;cv::meanStdDev(radius, mean, dev);double mean_radius = mean.at<double>(0, 0), dev_radius = dev.at<double>(0, 0);//std::cout << "radius mean---dev: " <<mean_radius << "dev_radius: " << dev_radius << std::endl;return (mean_radius > min_radius && dev_radius < max_dev);
}

6、顺/逆时针方向判断

//************************************
// Description: 将输入的point2d点集判断顺/逆时针方向
// Method:    IsClockwiseFromCross
// FullName:  IsClockwiseFromCross
// Access:    private
// Parameter: 二维点集 const std::vector<cv::Point2f> &point2ds
// Returns:   bool
// Author:    
// Date:      2018/08/28
// History:
//************************************
bool IsClockwiseFromCross(const std::vector<cv::Point2f> &point2ds) {int positive = 0, negative = 0;for (size_t i = 1; i < point2ds.size() - 1; i++) {//由i,i-1,i+1得到局部方向int status = WhichClockWise(point2ds.at(i - 1), point2ds.at(i), point2ds.at(i + 1));if (status == -1)negative++;else if (status == 1)positive++;}//  if (abs(positive - negative) < 5)//      std::cout << "[warning]: the clockwise may be wrong" << std::endl;//按正、反方向数量判断返回多的反向return (positive >= negative);
}
//************************************
// Description: 将输入的point2d点判断局部方向
// Method:    WhichClockWise
// FullName:  WhichClockWise
// Access:    private
// Parameter: 二维点a cv::Point2f a
// Parameter: 二维点b cv::Point2f b
// Parameter: 二维点c cv::Point2f c
// Returns:   int
// Author:    
// Date:      2018/08/28
// History:
//************************************
int WhichClockWise(cv::Point2f a, cv::Point2f b, cv::Point2f c) {double triangle_area = a.x * b.y - a.y * b.x + a.y * c.x - a.x * c.y + b.x * c.y - c.x * b.y;if (triangle_area < 0) return -1;else if (triangle_area > 0) return 1;return 0;
}

 

这篇关于3D手势识别(一)顺/逆时针画圈判断的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/727600

相关文章

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

Python中图片与PDF识别文本(OCR)的全面指南

《Python中图片与PDF识别文本(OCR)的全面指南》在数据爆炸时代,80%的企业数据以非结构化形式存在,其中PDF和图像是最主要的载体,本文将深入探索Python中OCR技术如何将这些数字纸张转... 目录一、OCR技术核心原理二、python图像识别四大工具库1. Pytesseract - 经典O

python判断文件是否存在常用的几种方式

《python判断文件是否存在常用的几种方式》在Python中我们在读写文件之前,首先要做的事情就是判断文件是否存在,否则很容易发生错误的情况,:本文主要介绍python判断文件是否存在常用的几种... 目录1. 使用 os.path.exists()2. 使用 os.path.isfile()3. 使用

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Python验证码识别方式(使用pytesseract库)

《Python验证码识别方式(使用pytesseract库)》:本文主要介绍Python验证码识别方式(使用pytesseract库),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录1、安装Tesseract-OCR2、在python中使用3、本地图片识别4、结合playwrigh

Python如何判断字符串中是否包含特殊字符并替换

《Python如何判断字符串中是否包含特殊字符并替换》这篇文章主要为大家详细介绍了如何使用Python实现判断字符串中是否包含特殊字符并使用空字符串替换掉,文中的示例代码讲解详细,感兴趣的小伙伴可以了... 目录python判断字符串中是否包含特殊字符方法一:使用正则表达式方法二:手动检查特定字符Pytho

使用Python和PaddleOCR实现图文识别的代码和步骤

《使用Python和PaddleOCR实现图文识别的代码和步骤》在当今数字化时代,图文识别技术的应用越来越广泛,如文档数字化、信息提取等,PaddleOCR是百度开源的一款强大的OCR工具包,它集成了... 目录一、引言二、环境准备2.1 安装 python2.2 安装 PaddlePaddle2.3 安装

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib