2016-03-02 3 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

Найти дефекты выпуклости во всех полученных контурах. Один из четырех основных дефектов должен быть рукой. –

+0

Хорошо, спасибо, я постараюсь исследовать об этом – Lily

ответ

1

Во-первых, резюме :: findContour() не только заполняет массив выходного контура, но также изменяет входной Mat изображение. Итак, если вы используете findContour() с глобальным экземпляром экземпляра Mat Mat, попробуйте findContour (src.clone(), dat и т. Д.), А не findContour (src, dat и т. Д.)

Во-вторых, переменная 'most_contour_index' инициализируется наружу для цикла (;;) и устанавливается на определенное значение ТОЛЬКО ЕСЛИ появляется больший контур, поэтому он может привести к ошибке Array за пределами границ.

Так что в вашем коде,

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); 
} 


Редакция:
Если цвет фона изображения ярче, чем ручной цвет, резюме :: 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

Затем попробуйте использовать CV_RETR_TREE в параметре findContours(). CV_RETR_CCOMP может возвращать весь фрейм, если ваш фоновый рисунок яркого цвета (и т. Д. Белый). Я добавлю это к своему ответу –

Смежные вопросы