在完成了之前提到的工作之后,发现在实际操作的时候,存在一定的问题:
(1)由于识别的是轮廓凸缺陷,所以得到的最终结果是一个点组,包括起始点、结束点、最远点和到最远点之间的距离。在实际运用中。想要用一个3D的手部模型与识别出来的手部进行绑定。因为涉及手掌整体和各个手指的移动,所以需要对手掌和手指分别进行定位。但是由于只保存了五个指尖点,所以采用平均的方法计算出中心点。由于指尖位置存在一定程度的跳变,所以实验效果并不理想,容易出现手掌和手指的分离。
(2)由于基于颜色识别,所以受到背景环境色的影响较大。当背景色过于杂乱或者接近肤色时,会产生一定的影响。目前的解决方案是,采购了外置摄像头,保持摄像头垂直角度从上向下拍摄,人手能够平摊在键盘区域上方。构思或许带上颜色比较鲜艳的手套也是一种解决方案。
下面是对问题(1)的解决方案。
要实现检测到的手部位置和环境中模型的实时更新,就需要一定的数据传递。将获取到的手部信息实时传递给环境中的模型,只需要在模型脚本中获取手部识别脚本上的变量即可。
这个过程中,需要注意的是,手部识别的脚本坐标属于UGUI的坐标,而模型的坐标属于世界坐标。直接采用坐标xyz值的传递,会导致位置出错,需要使用一个函数进行坐标之间的转换。
public Vector3 WorldToUI(Camera camera,Vector3 pos){
CanvasScaler scaler = GameObject.Find("Canvas").GetComponent<CanvasScaler>();
float resolutionX = scaler.referenceResolution.x;
float resolutionY = scaler.referenceResolution.y;
Vector3 viewportPos = camera.WorldToViewportPoint(pos);
Vector3 uiPos = new Vector3(viewportPos.x * resolutionX - resolutionX * 0.5f,
viewportPos.y * resolutionY - resolutionY * 0.5f,0);
return uiPos;
}
}
手掌的定位中,一个非常重要的定位点就是质心。
所谓质心,指物质系统上被认为质量集中于此的一个假想点。计算质心的基本思路如下:
1. 输入图像转换为二值图像
2. 通过连通组件标记算法找到所有的连通区域,并分别标记
3. 对每个连通区域运用计算几何距算法得到质心
4. 用不同颜色绘制连通区域与质心,输出处理后图像
Moments moment = Imgproc.moments (contour, false);
Point center = new Point (moment.m10 / moment.m00, moment.m01 / moment.m00);
//质心点
Imgproc.circle (rgbaMat, center, 6, new Scalar (0, 0, 255, 255), -1);
MatOfPoint conPointMat = contours [boundPos];
List<Point> conPoint = conPointMat.toList();
List<Point> fingerTips=new List<Point>();
其中moments函数可以获得图像的矩,并且根据计算几何矩的算法得到质心center。
我们选择使用蓝色在画面上标记图像的质心。

蓝色的线段涉及另一种寻找指尖的算法。我将在下一篇博客中详细说明。谢谢观看!