2012-11-21 205 views
1

我是openCV中的新人,我已經檢測到紙張邊緣,但是在邊緣畫線後我的結果圖像模糊不清,我如何在紙張邊緣繪製線條以便我的圖像質量不受影響。邊界檢測紙張opencv

我在想什麼。

我的代碼如下。

非常感謝。

enter image description here

-(void)forOpenCV 
{ 
    if(imageView.image != nil) 
    { 

     cv::Mat greyMat=[self cvMatFromUIImage:imageView.image]; 
     vector<vector<cv::Point> > squares; 

     cv::Mat img= [self debugSquares: squares: greyMat ]; 


     imageView.image =[self UIImageFromCVMat: img]; 

    } 

} 


- (cv::Mat) debugSquares: (std::vector<std::vector<cv::Point> >) squares : (cv::Mat &)image 
{ 
NSLog(@"%lu",squares.size()); 

// blur will enhance edge detection 

Mat blurred(image); 
medianBlur(image, blurred, 9); 

Mat gray0(image.size(), CV_8U), gray; 
vector<vector<cv::Point> > contours; 

// find squares in every color plane of the image 
for (int c = 0; c < 3; c++) 
{ 
    int ch[] = {c, 0}; 
    mixChannels(&image, 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(), cv::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<cv::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); 
      } 
     } 
    } 
} 

NSLog(@"%lu",squares.size()); 


for(size_t i = 0; i < squares.size(); i++) 
{ 


    cv:: Rect rectangle = boundingRect(Mat(squares[i])); 
    if(i==squares.size()-1)////Detecting Rectangle here 
    { 
     const cv::Point* p = &squares[i][0]; 


     int n = (int)squares[i].size(); 

     NSLog(@"%d",n); 



     line(image, cv::Point(507,418), cv::Point(507+1776,418+1372), Scalar(255,0,0),2,8); 

     polylines(image, &p, &n, 1, true, Scalar(255,255,0), 5, CV_AA); 



     fx1=rectangle.x; 
     fy1=rectangle.y; 
     fx2=rectangle.x+rectangle.width; 
     fy2=rectangle.y+rectangle.height; 


     line(image, cv::Point(fx1,fy1), cv::Point(fx2,fy2), Scalar(0,0,255),2,8); 


    } 



} 


return image; 
} 
+0

嗨@QueueOverFlow,我指的是你的opencv代碼做類似於你所做的事情。我對此有所懷疑。上述代碼中的函數角(arg1,arg2,arg3)是指什麼?你能幫我麼? – Ananth

+0

你可以添加角度功能嗎? –

回答

1

而不是

Mat blurred(image); 

你需要做的

Mat blurred = image.clone(); 

因爲第一行不復制的圖像,而只是創建第二個指針相同的數據。 當您模糊圖像時,您也正在更改原始圖像。 您需要做的是創建實際數據的實際副本並在此副本上進行操作。

OpenCV reference狀態:通過使用拷貝構造或賦值運算符,其中在右側它可以 是矩陣或表達

,見下文。同樣,如介紹中所述,矩陣分配是O(1)操作,因爲它只複製標題並增加參考計數器。

Mat :: clone()方法可用於在需要時獲取矩陣的完整副本(又名深度)。

+0

+1,現在圖像質量很好,但現在沒有檢測到紙張的邊緣,現在在完整視圖上繪製矩形 – QueueOverFlow

+0

您必須確保您使用模糊圖像進行輪廓提取。例如'mixChannels(&image,1,&gray0,1,ch,1);'應該可能是'mixChannels(&blurred,1,&gray0,1,ch,1);'。這是否解決了您的問題? – sietschie

+0

感謝您的回覆,但我已經修改了大部分代碼,我的這個問題已經解決了90%。我想知道我們如何裁剪邊界區域?請看看我的另一個問題..http://stackoverflow.com/questions/13098073/adjust-corners-and-crop-the-image-opencv – QueueOverFlow

1

第一個問題是容易通過對原始圖像的副本做整個處理解決。這樣,當你得到廣場的所有點後,你可以在原始圖像上畫線,它不會模糊。

第二個問題,即裁剪,可以通過在原始圖像中定義ROI(感興趣的區域)然後將其複製到新的Mat來解決。我已經證明,在this answer

// Setup a Region Of Interest 
cv::Rect roi; 
roi.x = 50 
roi.y = 10 
roi.width = 400; 
roi.height = 450; 

// Crop the original image to the area defined by ROI 
cv::Mat crop = original_image(roi); 

cv::imwrite("cropped.png", crop);