场景:前装摄像头
检测动作:单手指画圈,需要判断画圈方向和圈数。
步骤: (1)取得3D图像序列最前点;
(2)将最前点投影在2D平面上;
(3)中值滤波和平滑处理;
(4)得到2D点集进行线性插值;
(5)以重心为中心判断是否闭环;
(6)2D点集进行椭圆拟合,判断是否椭圆、椭圆半径和椭圆度范围;
(7) 2D点集进行圆拟合,计算半径均值和标准差;
(8)判断2D点集方向:顺/逆时针。
其中手的识别使用深度学习进行,根据TensorFlow训练完的模型判断出图像中有手且为单手指,
去掉背景、挖出只含有手的图像;中值滤波用的OpenCV medianBlur函数,其他主要函数算法如下:
Table of Contents
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)