2013-04-02 42 views
2

圖像中檢測最大的矩形我問上一個問題here及繼起我建立了下面的程序,我認爲會檢測大矩形答案的建議,但沒有檢測到矩形的。它確實在這個image上工作。使用OpenCV的

Original Image

Desired Image

我想該解決方案不僅這個形象,但這種不同的圖像上工作。下面的代碼的主要部分是從不同的答案在SO

我的完整方案:

#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

回答