【问题标题】:OpenCV3 Finger DetectionOpenCV3 手指检测
【发布时间】:2017-01-01 03:45:16
【问题描述】:

我对 OpenCV 还是很陌生,刚刚玩了一段时间,做了一些基本的事情,比如阈值图像等。我在 C++ 中使用 Visual Studio 2015 和 OpenCV3。我正在尝试检测使用相机举起的手指数量。例如,如果我举起 4 个手指,我希望程序告诉我检测到 4 个手指。到目前为止,我已经能够使用轮廓检测​​物体的边缘,例如相机中的整只手。代码如下:

#include "opencv2\opencv.hpp"

using namespace cv;

void on_trackbar(int, void*) {
    // Dummy function
}

int main(int argv, char** argc) {
    Mat frame;
    Mat grayFrame;
    Mat hsvFrame;
    Mat thesholdFrame;
    VideoCapture capture;

    //Trackbar variables (H,S,V)
    int H_MIN = 0;
    int H_MAX = 180;
    int S_MIN = 0;
    int S_MAX = 255;
    int V_MIN = 0;
    int V_MAX = 255;



    namedWindow("trackbar", 0);
    //create memory to store trackbar name on window
    char TrackbarName[50];
    sprintf(TrackbarName, "H_MIN");
    sprintf(TrackbarName, "H_MAX");
    sprintf(TrackbarName, "S_MIN");
    sprintf(TrackbarName, "S_MAX");
    sprintf(TrackbarName, "V_MIN");
    sprintf(TrackbarName, "V_MAX");

    createTrackbar("H_MIN", "trackbar", &H_MIN, H_MAX, on_trackbar);
    createTrackbar("H_MAX", "trackbar", &H_MAX, H_MAX, on_trackbar);
    createTrackbar("S_MIN", "trackbar", &S_MIN, S_MAX, on_trackbar);
    createTrackbar("S_MAX", "trackbar", &S_MAX, S_MAX, on_trackbar);
    createTrackbar("V_MIN", "trackbar", &V_MIN, V_MAX, on_trackbar);
    createTrackbar("V_MAX", "trackbar", &V_MAX, V_MAX, on_trackbar);


    capture.open(0);
    std::vector<std::vector<cv::Point> > contours;


    while (true){
        capture >> frame;
        waitKey(10);

        cvtColor(frame, hsvFrame, COLOR_BGR2HSV);
        //imshow("HSV", hsvFrame);

        inRange(hsvFrame, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX, S_MAX, V_MAX), thesholdFrame);
        findContours(thesholdFrame, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

        int largest_contour_area = 0;
        int largest_contour_area_index = 1;
        /*for (int i = 0; i < contours.size(); i++) {

            double contour_area = contourArea(contours[i], false);

            if (contour_area > largest_contour_area) {
                largest_contour_area = contour_area;
                largest_contour_area_index = i;
            }

        }*/

        drawContours(frame, contours, -1, (0, 255, 0), 3);
        putText(frame, "NO DETECTION", Point(25, 40), 2, 1, CV_RGB(255, 255, 0), 1, 8, false);

        imshow("Threshold", thesholdFrame);
        imshow("Camera", frame);
    }

}

搜索了一段时间后,我意识到仅隔离手部的轮廓可能很有用。被注释掉的“for”循环是我实现它的尝试。但是,它似乎不起作用。我确实意识到,一旦取消注释该部分,我就必须更改

drawContours(frame, contours, -1, (0, 255, 0), 3);

drawContours(frame, contours[largest_contour_area_index], -1, (0, 255, 0), 3);

这似乎不起作用。我不断收到此错误(当我取消注释 for 循环并将 drawContours 命令替换为上述命令时):

Unhandled exception at 0x00007FF8C1537788 in FingerDetection.exe: Microsoft C++ exception: cv::Exception at memory location 0x0000000C4CAFDB50.

此外,如果我确实设法让程序找到帧中最大轮廓的边缘(即手),我将如何继续检测手指的数量?我听说过关于凸包等的事情,但是我找不到任何好的解释。关于做什么的任何澄清或建议?请记住,我是 openCV 的新手。

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    您的第二个问题(“我将如何继续检测手指的数量”)可能有点过于宽泛,无法在这里回答。

    但第一个(即为什么你得到异常)似乎有一个简单的答案,我从 OpenCV 文档(2.4 版)中获得了我找到的drawContours 函数here

    据此,第二个参数必须是一个数组(轮廓),所以你不能简单地传递单个元素contours[largest_contour_area_index]

    如果你只想绘制一个轮廓,你仍然需要传递整个数组,然后将要绘制的轮廓的索引作为第三个参数(而不是-1):

    drawContours(frame, contours, largest_contour_area_index, (0, 255, 0), 3);
    

    作为附加说明,最好确保largest_contour_area_index 的值小于数组中的轮廓数。鉴于您当前的代码,可能存在永远不会执行 for 循环体的情况,并且初始化为 1 值的 largest_contour_area_index 可能太大。

    【讨论】:

    • 这似乎已经修复了我的代码。我将 -1 替换为 maximum_contour_area_index。
    • 我遇到了另一个问题。我的手似乎从手腕处连接到我纯白墙壁的一部分中,形成一个非常大的轮廓。什么是隔离我的手而不是其他任何东西的最佳方法。
    猜你喜欢
    • 2013-11-22
    • 1970-01-01
    • 2015-07-15
    • 2013-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    相关资源
    最近更新 更多