2016-03-02 248 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可能会返回整个帧。我会将其添加到我的答案中 –