2017-06-29 1 views
0

J'ai posé une question similaire mais pour python en utilisant un tableau numpy Opencv Python Crop Image Using Numpy Array. Je cherche à recadrer une image basée sur ses coins. Voici une photo pour démontrer l'objectif. Cropping GoalOpencv C++ Crop Image basée sur les changements de coins

J'ai un code python qui fait l'affaire mais qui doit le convertir en C++. Ce qui suit est mon code python de travail et le code C++ partiel respectivement.

def crop(self,image): 
    grayed = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) 
    (_,thresh) = cv2.threshold(grayed,1,255,cv2.THRESH_BINARY) 
    result, contours, _= cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 
    x, y = [], [] 
    for i in range(len(contours)): 
     for j in range(len(contours[i])): 
      x.append(contours[i][j][0][0]) 
      y.append(contours[i][j][0][1]) 
    x1, x2, y1, y2 = min(x), max(x), min(y), max(y) 
    cropped = image[y1:y2, x1:x2] 
    return cropped 

C++ code:

Mat crop(Mat image){ 
    Mat cropped, grayed, thresh, result; 
    vector<vector<Point>> contours; 
    vector<Vec4i> hierarchy; 
    cvtColor(image, grayed, CV_BGR2GRAY); 
    threshold(grayed, thresh, 1, 255,THRESH_BINARY); 
    findContours(thresh, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); 

    std::vector<int> x,y; 
    cout << contours.size() << endl; 
    for(int i=0; i < contours.size();i++){ 
     for(int j = 0; j < contours.at(i).size();j++){ 
      x.push_back(contours.at(i).at(j).x); 
      y.push_back(contours.at(i).at(j).y); 
     } 
    } 

    cout << x.size() << endl; 
    cout << y.size() << endl; 

    vector<int>::iterator it = max(begin(x), end(x)); 
    int x1 = (*it); 
    it = max(begin(x), end(x)); 
    int x2 = *it; 
    it = min(begin(y), end(y)); 
    int y1 = *it; 
    it = max(begin(y), end(y)); 
    int y2 = *it; 

    cout << x1 << " " << x2 << " " << y1 << "  " << y2 << endl; 

    Rect rect (x1,y1,x2-x1,y2-y1); 
    cropped = image(rect); 
    return cropped; 
} 
+0

En Python, '' x' et y' sont simplement des listes d'entiers. Sachant cela, pourquoi en faire des vecteurs de vecteurs de vecteurs de Points en C++? –

+0

À part cela, vous êtes presque là - utilisez des vecteurs d'entiers, à l'intérieur des boucles insérez toutes les coordonnées x et y pour chaque point de chaque contour. Ensuite quelque chose comme 'std :: minmax_element', et enfin' operator() 'sur l'image d'entrée pour extraire la sous-région. Donner un coup de feu. –

+0

@ DanMašek Les vecteurs de vecteurs de vecteurs de points étaient moi travaillant beaucoup et cerveau se faire frire. Ma pensée était x et y est une liste donc je l'ai fait un vecteur et puisque j'ajoutais des contours j'ai ajouté leur type résultant dans le chaos. Pourriez-vous élaborer plus sur la façon d'insérer les coordonnées x et y pour chaque point dans chaque compteur éventuellement. L'autre partie a un sens total. Merci pour ton aide! –

Répondre

0
Mat crop(Mat image){ 
Mat cropped, grayed, thresh, result; 
vector<vector<Point>> contours; 
vector<Vec4i> hierarchy; 
cvtColor(image, grayed, CV_BGR2GRAY); 
threshold(grayed, thresh, 1, 255,THRESH_BINARY); 
findContours(thresh, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); 

vector<int> x,y; 
for(int i=0; i < contours.size();i++){ 
    for(int j = 0; j < contours.at(i).size();j++){ 
     x.push_back(contours[i][j].x); 
     y.push_back(contours[i][j].y); 
    } 
} 

auto xVals = std::minmax_element(x.begin(), x.end()); 
auto yVals = std::minmax_element(y.begin(), y.end()); 

Rect rect (*xVals.first,*yVals.first,(*xVals.second)-(*xVals.first),(*yVals.second)-(*yVals.first)); 
cropped = image(rect); 
return cropped; 

}

0
cv::Mat crop(cv::Mat image){ 
    cv::Mat cropped, grayed, thresh, result; 
    std::vector < std::vector <cv::Point>> contours; 
    std::vector<cv::Vec4i> hierarchy; 
    cvtColor(image, grayed, cv::COLOR_BGR2GRAY); 
    threshold(grayed, thresh, 1, 255, cv::THRESH_BINARY); 
    findContours(result, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0)); 
    std::vector<int> x, y; 

    for (int i = 0; i < contours.size(); i++){ 
     for (int j = 0; j <= contours.at(i).size(); j++){ 
      x.push_back(contours.at(i).at(j).x); 
      y.push_back(contours.at(i).at(j).y); 
     } 
    } 
    int x1 = std::min_element(x.begin(), x.end()); 
    int x2 = std::max_element(x.begin(), x.end()); 
    int y1 = std::min_element(y.begin(), y.end()); 
    int y2 = std::max_element(y.begin(), y.end()) 

    cv::Rect rect(x1, y1, x2 - x1, y2 - y1); 
    cropped = image(rect); 

    return cropped; 
} 

Essayez cette

+0

Merci pour la suggestion. Malheureusement, quand j'ai essayé votre code, je reçois: Pas de conversion viable de 'std :: __ 1 :: __ wrap_iter ' à 'int' Donc, j'ai changé le ints au vecteur :: itérateur x1 ect mais je ne peux pas obtenir le rectangle comme il le faut ints. –