2013-04-02 3 views
2

를 사용하여 이미지에서 가장 큰 사각형을 감지 나는 이전 질문 here 물어 내가 큰 사각형을 감지 것이라고 생각 아래의 프로그램을 내장 대답에서 조언을 다음하지만 모든 사각형을 감지하지 않습니다. 이건 image에서 작동합니다. OpenCV의

Desired Image

Original Image 나는 해결책이 이미지하지만,이 종류의 서로 다른 이미지뿐만 아니라 작업 할. (결국 두 번째로 큰 이상) http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html 가장 큰 윤곽해야한다 - 당신이 findContours에게 기능을 사용하여 쉽게 할 수 있다고 생각

#include <cv.h> 
#include <highgui.h> 
using namespace cv; 
using namespace std; 

double angle( Point pt1, Point pt2, Point pt0) { 
    double dx1 = pt1.x - pt0.x; 
    double dy1 = pt1.y - pt0.y; 
    double dx2 = pt2.x - pt0.x; 
    double dy2 = pt2.y - pt0.y; 
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); 
} 

void find_squares(Mat& image, vector< vector< Point> >& squares) 
{ 
    // blur will enhance edge detection 
    Mat blurred(image); 
    medianBlur(image, blurred, 9); 

    Mat gray0(blurred.size(), CV_8U), gray; 
    vector< vector< Point> > contours; 

    // find squares in every color plane of the image 
    for (int c = 0; c < 3; c++) 
    { 
     int ch[] = {c, 0}; 
     mixChannels(&blurred, 1, &gray0, 1, ch, 1); 

     // try several threshold levels 
     const int threshold_level = 2; 
     for (int l = 0; l < threshold_level; l++) 
     { 
      // Use Canny instead of zero threshold level! 
      // Canny helps to catch squares with gradient shading 
      if (l == 0) 
      { 
       Canny(gray0, gray, 10, 20, 3); // 

       // Dilate helps to remove potential holes between edge segments 
       dilate(gray, gray, Mat(), Point(-1,-1)); 
      } 
      else 
      { 
        gray = gray0 >= (l+1) * 255/threshold_level; 
      } 

      // Find contours and store them in a list 
      findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

      // Test contours 
      vector< Point> approx; 
      for (size_t i = 0; i < contours.size(); i++) 
      { 
        // approximate contour with accuracy proportional 
        // to the contour perimeter 
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true); 

        // Note: absolute value of an area is used because 
        // area may be positive or negative - in accordance with the 
        // contour orientation 
        if (approx.size() == 4 && 
          fabs(contourArea(Mat(approx))) > 1000 && 
          isContourConvex(Mat(approx))) 
        { 
          double maxCosine = 0; 

          for (int j = 2; j < 5; j++) 
          { 
            double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1])); 
            maxCosine = MAX(maxCosine, cosine); 
          } 

          if (maxCosine < 0.3) 
            squares.push_back(approx); 
        } 
      } 
     } 
    } 
} 

void find_largest_square(const vector<vector <Point> >& squares, vector<Point>& biggest_square) { 
    if (!squares.size()) { 
     return; 
    } 

    int max_width = 0; 
    int max_height = 0; 
    int max_square_idx = 0; 
    const int n_points = 4; 

    for (size_t i = 0; i < squares.size(); i++) { 
     Rect rectangle = boundingRect(Mat(squares[i])); 
     if ((rectangle.width >= max_width) && (rectangle.height >= max_height)) { 
      max_width = rectangle.width; 
      max_height = rectangle.height; 
      max_square_idx = i; 
     } 
    } 
    biggest_square = squares[max_square_idx]; 

} 

int main(int argc, char* argv[]) 
{ 
    Mat img = imread(argv[1]); 
    if (img.empty()) 
    { 
     cout << "!!! imread() failed to open target image" << endl; 
     return -1;   
    } 
    vector< vector< Point> > squares; 
    find_squares(img, squares); 
    vector<Point> largest_square; 
    find_largest_square(squares, largest_square); 
    for (int i = 0; i < 4; ++i) { 
     line(img, largest_square[i], largest_square[(i+1)%4], Scalar(0, 255, 0), 1, CV_AA); 
    } 
    imwrite("squares.png", img); 
    imshow("squares", img); 
    waitKey(0); 
    return 0; 
} 
+0

주의 깊게 작성한 질문에 너무 많은 후속 질문을하고 있습니다. 우리는 * 지금까지 시도한 것을 묻습니다. – karlphillip

+0

죄송합니다. 질문에 대해 오해했습니다. 나는 나중에 대답 할 수있다. 저녁 시간. – karlphillip

+0

:) 문제가 없습니다. 지도 해줘서 고마워. – birdy

답변

1

: 아래의 코드의 주요 부분은 SO

내 전체 프로그램에 다른 대답에서입니다 검은 사각형의 등고선. 그런 다음이 등고선을 둘러싸는 가장 작은 직사각형을 찾으십시오 (가장 큰/가장 작은 x/y 좌표를 가진 점을 찾으십시오).