2017-09-13 8 views
0

J'essaie actuellement de créer un programme qui trouve les bords d'un reçu, puis le recadre en conséquence. J'ai utilisé ce code pour le faire:Recherche des plus grands contours 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; 
    } 
} 

Ce code trouve les contours très bien, mais ne les filtre pas correctement. Par exemple, les images suivantes:

enter image description here enter image description here

L'image à gauche représente tous les contours alors que l'image à droite représentent juste la cible. Je me demande comment je peux changer mon code pour que je reçoive toujours les bords du reçu pour la cible.

+0

Couleur Segmentez l'image et trouvez les contours. Pas besoin de bords. ** vector plus grand = contours [contours.size() - 1] ** vous obtient le glissement blanc après le tri. Vous pouvez utiliser ** boundingRect (contours [i]) ** si vous avez besoin de points rectangle hors du contour. –

Répondre

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

Quel serait l'équivalent de la méthode de tri en C++? Il me semble que vous ne pouvez trier par zone. –

+0

Aussi la question demander le code C++ –

0

Tout d'abord, votre problème est que vous ne trouvez pas le contour droit du tout à cause d'un bruit. Vous devriez appliquer un filtrage à votre image afin de rendre l'arrière-plan lisse et uniforme. Par exemple, essayez cv::medianBlur() avec différentes tailles de noyau - cela diminuera la netteté de l'arrière-plan. Deuxièmement, après avoir trouvé tous les contours sur l'image, vous voudrez (probablement) obtenir le plus grand. Dans ce cas, vous pouvez utiliser std::sortfunction votre vecteur-de-vecteurs (je veux dire contours) en fournissant un argument correct comp. Ce dernier est une fonction qui devrait prendre 2 contours et retourner true si le premier contour est plus grand que le second. Pour comparer deux contours, vous devez utiliser la fonction cv::contourArea() comme mentionné précédemment.

Ou, vous pouvez écrire une fonction simple comme ça:

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

Et vous trouverez votre plus grand contour que contours.at(getMaxAreaContourId(contours)).