2017-09-13 193 views
0

我目前正在嘗試創建一個程序來查找收據的邊緣,然後相應地裁剪它。我用這個代碼來做到這一點:查找最大的輪廓C++

vector<vector<cv::Point> > contours; 
vector<Vec4i> hierarchy; 

findContours(edged, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); 
sort(contours.begin(), contours.end(), compareContourAreas); 

vector<cv::Point> target; 
for(int i = 0; i < contours.size(); i++){ 
    vector<cv::Point> c = contours[i]; 
    double p = arcLength(c, true); 
    vector<cv::Point> approx; 
    approxPolyDP(c, approx, 0.02*p, true); 
    if (approx.size() == 4) { 
     target = approx; 
     break; 
    } 
} 

這段代碼發現輪廓很好,但沒有正確地過濾它們。例如,將在以下圖像

enter image description here enter image description here

在左邊的圖像表示所有輪廓而圖像向右只是表示目標。我想知道如何更改我的代碼,以便始終收到目標收據的邊緣。

+0

顏色細分圖像並找到輪廓。不需要邊緣。 **矢量最大=輪廓[輪廓。尺寸()​​ - 1] **讓你在排序後滑出。如果需要輪廓外的矩形點,可以使用** boundingRect(輪廓[i])**。 –

回答

0
def sort(n): 
    return n.size 


image = cv2.imread("image.jpg",-1) 

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 

ret, binary = cv2.threshold(gray, 210, 255, cv2.THRESH_BINARY) 

img,contours,hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 

ncontours = sorted(contours, key=sort,reverse=True) 

rect = cv2.minAreaRect(ncontours[0]) 
box = cv2.boxPoints(rect) 
box = np.int0(box) 
cv2.drawContours(image, [box], 0, (0,0,255),2) 

result

+0

相當於C++中的排序方法是什麼?在我看來,你只能按區域排序。 –

+0

此外問題要求C++代碼 –

0

首先,你的問題是,你沒有找到合適的輪廓,因爲在所有的噪聲中。您應該對圖像應用一些濾鏡以使背景平滑和均勻。例如,嘗試使用不同內核大小的cv::medianBlur() - 它會降低背景的清晰度。其次,在圖像上找到所有輪廓之後,您(可能)想要獲得最大的輪廓。在這種情況下,您可以通過提供正確的comp參數,使用std::sortfunction您的載體向量(我的意思是contours)。後者是一個函數,如果第一個輪廓大於第二個輪廓,則該函數應該取2個輪廓並返回true。要比較兩個輪廓,應使用前面提到的功能cv::contourArea()

或者,你可以寫一個簡單的函數那樣:

int getMaxAreaContourId(vector <vector<cv::Point>> contours) { 
    double maxArea = 0; 
    int maxAreaContourId = -1; 
    for (int j = 0; j < contours.size(); j++) { 
     double newArea = cv::contourArea(contours.at(j)); 
     if (newArea > maxArea) { 
      maxArea = newArea; 
      maxAreaContourId = j; 
     } 
    return maxAreaContourId; 
} 

然後你發現你的最大的輪廓contours.at(getMaxAreaContourId(contours))