opencv - OpenCV - 确定手腕的位置
问题描述
我需要确定手腕在框架中的位置,其中包含人体的部分手臂和匹配的手。到目前为止,我已经隔离了手和手臂,并且能够在其周围绘制多边形和船体曲线:
我通过简单的二进制阈值和自动轮廓拟合来实现这个结果。
基于此,我想提取手腕的位置。这需要适用于手/手腕的所有方向。
然而,对于使用 OpenCV 来说相当新,我不清楚确定/隔离手腕位置的最佳方法是什么。我对此有各种想法:
- 手臂部分相当直。也许在轮廓多边形上进行简单的线检测可能会完成获得腋下直线的工作。
- 以某种方式将轮廓多边形分成多个部分。基本上,可以公平地假设手腕的位置在两臂之间的距离最小,轮廓在腋下。有没有办法沿着多边形找到那个点,然后“切割”或“分割”多边形以获得两个?从那里我会有一个多边形代表一个应该很容易使用的矩形。
- 使用沿着使用 拟合的多边形的主轴迭代的方法
fitLine()
,测量多边形的两个相对点之间的距离,找到最短距离。
不幸的是,我缺乏在这里做出正确选择的经验——甚至没有想出更好的主意。
我将不胜感激任何实现这一目标的想法和指示。在使用 Haar 级联进行手部检测和跟踪以及基本身体部位匹配时,我可以找到很多有价值的研究材料。不幸的是,我找不到将这些技术应用于我的用例的方法。
这里有一些可以使用的原材料(图片和视频):(Google Drive Link!):https ://drive.google.com/drive/folders/1hU4hGw5dYtVrcXTq8TYWCWfcLWjT-ZJU?usp=sharing
解决方案
做法:我利用了手臂侧的优势。直到碰到手,手臂的厚度几乎相同。
假设:我假设手臂将垂直进入屏幕进行编码。否则我的代码可能不起作用。我尝试了您共享的所有图像,并且它对所有人都正常工作。
我的步骤:
- 制作一个简单的分割方法,只获取图像的所需部分
- 从手臂一侧开始计算每列的非黑色像素。
- 直到击中与先前列计数不同的列,您仍处于手臂一侧。当你击球时,你到达了手腕。
注意:我通过实验确定了阈值。
以下是结果和代码:
输入图像:
分割后:
算法后的输出:
代码:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <cstdlib>
using namespace cv;
using namespace std;
int main() {
Mat src, gray, blur_image, threshold_output;
// take input image
src = imread("/ur/image/directory/image_01.jpg", 1);
// convert to grayscale
cvtColor(src, gray, COLOR_BGR2GRAY);
// add blurring to the input image
medianBlur(gray,gray,9);
// Apply a segmentation to arm
for(int i=0; i<gray.rows; i++)
for(int j=0;j<gray.cols; j++)
if(gray.at<uchar>(Point(j,i))<110)
gray.at<uchar>(Point(j,i)) = 0;
//Creat a bgr mat to show the results clearly
Mat copy_gray = gray;
cvtColor(copy_gray,copy_gray,CV_GRAY2BGR);
double sum = 0;
int loop_cnt = 0,enter = 1;
Point first,second;
for(int j=gray.cols-1; j>=0; j--)
{
loop_cnt++;
int counter = 0,ff=1,enter2 = 1;
for(int i=0;i<gray.rows; i++)
{
if(gray.at<uchar>(Point(j,i))!=0 && enter)
{
if(ff)
first = Point(j,i);
counter++;
ff = 0;
}
if(!ff && gray.at<uchar>(Point(j,i))==0 && enter2)
{
second = Point(j,i);
enter2 = 0;
}
}
sum += (double)counter;
double average = sum/(double)(loop_cnt);
if(abs(average-counter)>20.0 && enter)
{
line(copy_gray,Point(j,0),Point(j,500),Scalar(0,255,0),5);
enter = 0;
}
}
int distance = norm(second-first)/2;
circle(copy_gray,Point(first.x,first.y+distance),20,Scalar(0,0,255),5);
imshow("Result",copy_gray);
waitKey(0);
return 0;
}
推荐阅读
- python - 使用带有 queue.put() 的地图?
- c# - 运行多个 Http 调用时的 Sigabrt -6 xamarin.forms 线程池
- php - Phalcon - ::find() 与关系条件
- webpack - manifest.json 中缺少条目
- javascript - 在这种情况下,document.write 会给我带来麻烦吗?
- c# - 预订引擎中的体验商店日期时间
- http - IIS 网站只允许 https 连接,不允许 http
- node.js - Joi 正则表达式不被识别为正则表达式模式
- amazon-web-services - CloudFormation 因小写而无法找到 RDS 子网组
- c# - C# 错误:邮箱不可用。客户端无权作为此发件人发送