2016-03-02 240 views
0

我正在研究手部識別系統,我是初學者。我試圖通過找到最大的輪廓(即手)來檢測手,但它在整個框架上畫一個矩形而不是手。我該如何解決它?在opencv中尋找最大的輪廓

#include "stdafx.h" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 
#include "opencv\cv.h" 
#include <iostream> 
#include <stdlib.h> 
#include <stdio.h> 

using namespace cv; 
using namespace std; 




int main() 
{ 
VideoCapture cap("pathaka.MP4"); // open the default camera 
if (!cap.isOpened()) // check if we succeeded 
return -1; 

Mat edges; 
namedWindow("edges", 1); 

int largest_area = 0; 
int largest_contour_index = 0; 
Rect bounding_rect; 

for (;;) 
{ 
    Mat frame; 
    cap >> frame; // get a new frame from video 
    Mat dst(frame.rows, frame.cols, CV_8UC1, Scalar::all(0)); 
    cvtColor(frame, edges, CV_BGR2GRAY); 
    threshold(edges, edges, 22, 44, THRESH_BINARY); 
    GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5); 
// Canny(edges, edges, thresh, thresh*2, 3); 
    int erosion_type = MORPH_ELLIPSE; 
    int erosion_size = 0; 
    Mat element = getStructuringElement(erosion_type, Size(2 * erosion_size + 1, 2 * erosion_size + 1), Point(erosion_size, erosion_size)); 
    erode(edges, edges, element); 
    dilate(edges, edges, element); 

    vector<vector<Point>>contours; //Vector for storing contour 
    vector<Vec4i> hierarchy; 

    findContours(edges, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image 

    for (int i = 0; i< contours.size(); i++) // iterate through each contour. 
    { 
     double a = contourArea(contours[i], false); // Find the area of contour 
     if (a>largest_area){ 
      largest_area = a; 
      largest_contour_index = i;    //Store the index of largest contour 
      bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour 
     } 

    } 
    Scalar color(255, 255, 255); 
    drawContours(dst, contours, largest_contour_index, color, CV_FILLED, 8, hierarchy); // Draw the largest contour using previously stored index. 
    rectangle(frame, bounding_rect, Scalar(0, 255, 0), 1, 8, 0); 

    imshow("src", frame); 
    imshow("largest contour", dst); 
    if (waitKey(30) >= 0) break; 

} 

// the camera will be deinitialized automatically in VideoCapture destructor 




return 0; 
} 
+0

嘗試繪製所有輪廓來調試此。 –

+0

在所有檢索的輪廓中查找凸度缺陷。應該是一個有4個重大缺陷的人。 –

+0

好的,謝謝,我會盡力調查那 – Lily

回答

1

首先, CV :: findContour()不僅填補輸出輪廓陣列而且還改變輸入墊的圖像。因此,如果您使用findContour()與全局源Mat圖像實例,請嘗試findContour(src.clone(),dat等。)而不是findContour(src,dat等)。

二, 變量'largest_contour_index'被初始化爲(;;)循環的外部,並設置爲特定值,只有當出現較大的輪廓時,纔會導致數組越界出錯。

在你的代碼

所以,

largest_contour_index = -1; 
largest_area = 0; 

findContours(edges.clone(), contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image 

for (int i = 0; i< contours.size(); i++) // iterate through each contour. 
{ 
    double a = contourArea(contours[i], false); // Find the area of contour 
    if (a>largest_area){ 
     largest_area = a; 
     largest_contour_index = i;    //Store the index of largest contour 
     bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour 
    } 

} 

if(largest_contour_index >= 0) 
{ 
    Scalar color(255, 255, 255); 
    drawContours(dst, contours, largest_contour_index, color, CV_FILLED, 8, hierarchy); // Draw the largest contour using previously stored index. 
    rectangle(frame, bounding_rect, Scalar(0, 255, 0), 1, 8, 0); 
} 


編輯:
如果圖像的背景顏色是比手的色彩,明亮的CV :: findContour()與CV_RETR_CCOMP將首先檢測整體框架。
請嘗試使用CV_RETR_TREE。

findContours(edges.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image 

如果同樣的事情發生,有3種選擇:

1.反轉你墊的顏色。
請注意,這將消耗少量時間。

cv::cvtColor(edges, edges, CV_BRG2GRAY); // if your org image is not grayscale 
edges = 255-edges; 


2.選擇第二個最大的一個。

for (int i = 1; i< contours.size(); i++) // iterate through each contour. 
{...} 


3.忽略如果一個輪廓的大小几乎等於墊的大小。

int matSize = (edges.rows * edges.cols) * 0.95; // 95% size of image 
. 
. 
for (int i = 0; i< contours.size(); i++) // iterate through each contour. 
{ 
    double a = contourArea(contours[i], false); // Find the area of contour 
    if(a > matSize) continue; 
    . 
    . 
} 

3.使用層次結構。
我建議你使用層次結構,儘管起初使用起來有些複雜。
read this page for using hierarchy

+0

感謝您的回覆,但它仍然給我整個框架。 – Lily

+0

然後嘗試在函數findContours()參數中使用CV_RETR_TREE。如果圖像背景是明亮的顏色(如白色),CV_RETR_CCOMP可能會返回整個幀。我會將其添加到我的答案中 –