我需要确定手腕在人的手臂和匹配手部的框架中的位置。
到目前为止,我已经隔离了手和手臂,并且能够在其周围绘制多边形和船体曲线:

opencv - OpenCV-确定手腕的位置-LMLPHP

我通过简单的二进制阈值和自动轮廓拟合实现了此结果。

基于此,我想提取手腕的位置。这需要适用于手/腕的所有方向。

但是,对于使用OpenCV来说还很陌生,我不清楚确定/隔离手腕位置的最佳方法是什么。我对此有各种想法:

  • 手臂部分很直。在轮廓多边形上进行简单的直线检测可能会完成工作,以获取下臂的直线。
  • 以某种方式将轮廓多边形分成多个部分。基本上可以假设腕部的位置在两条与下臂轮廓一致的手臂之间的距离最小。有没有一种方法可以沿着多边形找到该点,然后“切割”或“分割”多边形以获得两个?从那里,我将有一个多边形,代表一个应该易于使用的矩形。
  • 使用一种方法,该方法沿着使用fitLine()拟合的多边形的主轴进行迭代,测量多边形的两个相对点之间的距离,找到最短的距离。

  • 不幸的是,我缺乏在这里做出正确选择的经验,甚至没有更好的主意。

    我会很感激实现这一目标的任何想法和指示。当涉及到使用Haar级联进行的手部检测和跟踪以及基本 body 部位匹配时,我可以找到很多有值(value)的研究 Material 。不幸的是,我找不到在我的用例中应用这些技术的方法。

    以下是一些可使用的原始 Material (图像和视频):(Google云端硬盘链接!):https://drive.google.com/drive/folders/1hU4hGw5dYtVrcXTq8TYWCWfcLWjT-ZJU?usp=sharing

    最佳答案

    方法:我利用了手臂方面的优势。直到碰到手,手臂的厚度几乎相同。

    假设:我通过假设手臂将垂直进入屏幕来进行编码。否则我的代码可能无法正常工作。我尝试了所有共享的图像,并且所有图像均正常工作。

    我的步骤:

  • 制作简单的分割方法以仅获取图像的一部分
  • 从手臂开始,开始计算每个列的非黑色像素。
  • 在击中不同于前一列计数的列之前,您仍然处于手臂一侧。当您击打时,您到达了手腕。

  • 注意:我通过实验确定了阈值。

    以下是结果和代码:

    输入图像:

    opencv - OpenCV-确定手腕的位置-LMLPHP

    细分后:

    opencv - OpenCV-确定手腕的位置-LMLPHP

    算法后的输出:

    opencv - OpenCV-确定手腕的位置-LMLPHP

    码:
    #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;
    }
    

    08-24 23:53