2017-01-01 62 views
2

我對OpenCV相當陌生,剛剛玩了一段時間,做了一些基本的事情,比如閾值圖像等等。我在C++中使用Visual Studio 2015和OpenCV3。我正在嘗試檢測使用相機時手指的手指數量。例如,如果我拿着4個手指,我希望程序告訴我有4個手指被檢測到。到目前爲止,我已經能夠使用輪廓檢測​​物體的邊緣,例如我整個手在相機中的邊緣。這裏是代碼:OpenCV3手指檢測

#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非常陌生。

回答

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循環的主體從未執行的情況,並且largest_contour_area_index(初始值爲1)可能太大。

+0

這似乎已經修復了我的代碼。我用largest_contour_area_index替換了-1。 – FShiwani

+0

雖然我有另一個問題。我的手似乎在手腕上的白色部分壁上連接起來,形成非常大的輪廓。什麼是隔離我的手和別的什麼的最佳方式。 – FShiwani