2016-04-17 6 views
0

Ich versuche, die Werte für Höhe und Breite zu finden, um den Aspekt Ration des Objekts mit der Kontur eines Bildes mit dem folgenden Code wiederherzustellen, aber nicht erfolgreich, da die Der Code erzeugt viele Rechtecke im gesamten Bild, wenn ich ein einzelnes Rechteck um das Objekt herum erstellen möchte. Ich versuche, dieses Rechteck zu erstellen, weil ich nicht weiß, ob es eine andere Möglichkeit gibt, die Höhe und Breite (oder sogar das Seitenverhältnis) anders als diese zu erhalten.OpenCV - Suchen von Höhe und Breite eines konturierten Bildes

*** RNG rng (12345); // Globale Variable zum Zeichnen von Rechtecken und Kreisen für die Konturen von Bildern.

/*Load the image*/ 
Mat img_bgr = imread("img.jpg", 1); 
if (img_bgr.empty()){ 
    cout << "No image..." << endl; 
    return -1; 
} 

/*Display the image*/ 
namedWindow("Original Image", WINDOW_NORMAL); 
imshow("Original Image", img_bgr); 

/*Conversion to HSV*/ 
Mat img_hsv; 
cvtColor(img_bgr, img_hsv, CV_BGR2HSV); 

/*Extracting colors - HSV*/ 
Mat green, yellow, brown; 

//Yellow 
inRange(img_hsv, Scalar(25, 0, 0), Scalar(36, 255, 255), yellow); //until 33 - consider "yellow" - from there up to 36 - consider for chlorosis 
imwrite("c:\\test\\results\\yellow.jpg", yellow); 

//Green 
inRange(img_hsv, Scalar(37, 0, 0), Scalar(70, 255, 255), green); //Consider lower as 37 
imwrite("c:\\test\\results\\green.jpg", green); 

//Brown 
inRange(img_hsv, Scalar(10, 0, 0), Scalar(20, 255, 255), brown); 
imwrite("c:\\test\\results\\brown.jpg", brown); 

namedWindow("Yellow", WINDOW_NORMAL); 
imshow("Yellow", yellow); 

namedWindow("Green", WINDOW_NORMAL); 
imshow("Green", green); 

namedWindow("Brown", WINDOW_NORMAL); 
imshow("Brown", brown); 

/*Finding Contours of the Thresholded images*/ 
vector<std::vector<Point>>green_cnt; 
vector<std::vector<Point>>yellow_cnt; 
vector<std::vector<Point>>brown_cnt; 

//Green Contour 
findContours(green, green_cnt, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 

//Draw the Contours - Green 
Mat green_cnt_draw(green.size(), CV_8UC3, Scalar(0, 0, 0)); 
Scalar green_cnt_colors[3]; 
green_cnt_colors[0] = Scalar(0, 255, 0); 
green_cnt_colors[1] = Scalar(0, 255, 0); 
green_cnt_colors[2] = Scalar(0, 255, 0); 

for (size_t idx_green = 0; idx_green < green_cnt.size(); idx_green++){ 
    drawContours(green_cnt_draw, green_cnt, idx_green, green_cnt_colors[idx_green % 3]); 
} 

namedWindow("Green - Contours", CV_WINDOW_NORMAL); 
imshow("Green - Contours", green_cnt_draw); 

//Yellow Contour 
findContours(yellow, yellow_cnt, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 

//Draw the Contours - Yellow 
Mat yellow_cnt_draw(yellow.size(), CV_8UC3, Scalar(0, 0, 0)); 
Scalar yellow_cnt_colors[3]; 
yellow_cnt_colors[0] = Scalar(0, 255, 255); 
yellow_cnt_colors[1] = Scalar(0, 255, 255); 
yellow_cnt_colors[2] = Scalar(0, 255, 255); 

for (size_t idx_yellow = 0; idx_yellow < yellow_cnt.size(); idx_yellow++){ 
    drawContours(yellow_cnt_draw, yellow_cnt, idx_yellow, yellow_cnt_colors[idx_yellow % 3]); 
} 

namedWindow("Yellow - Contours", CV_WINDOW_NORMAL); 
imshow("Yellow - Contours", yellow_cnt_draw); 

//Brown Contour 
findContours(brown, brown_cnt, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 

//Draw the Contours - Brown 
Mat brown_cnt_draw(brown.size(), CV_8UC3, Scalar(0, 0, 0)); 
Scalar brown_cnt_colors[3]; 
brown_cnt_colors[0] = Scalar(42, 42, 165); 
brown_cnt_colors[1] = Scalar(42, 42, 165); 
brown_cnt_colors[1] = Scalar(42, 42, 165); 

for (size_t idx_brown = 0; idx_brown < brown_cnt.size(); idx_brown++){ 
    drawContours(brown_cnt_draw, brown_cnt, idx_brown, brown_cnt_colors[idx_brown % 3]); 
} 

namedWindow("Brown - Contours", CV_WINDOW_NORMAL); 
imshow("Brown - Contours", brown_cnt_draw); 


/*Creating rectangles around the contours*/ 
//Green 
vector<vector<Point>>green_contours_poly(green_cnt.size()); 
vector<Rect>green_boundRect(green_cnt.size()); 
vector<Point2f>green_center(green_cnt.size()); 
vector<float>green_radius(green_cnt.size()); 

for (int i = 0; i < green_cnt.size(); i++){ 
    approxPolyDP(Mat(green_cnt[i]), green_contours_poly[i], 3, true); 
    green_boundRect[i] = boundingRect(Mat(green_cnt[i])); 
    minEnclosingCircle((Mat)green_contours_poly[i], green_center[i], green_radius[i]); 
} 

//Green - Draw polygonal contour AND bounding rects + circles 
Mat green_drawRecAndCirc = Mat::zeros(green.size(), CV_8UC3); 
for (int i = 0; i < green_cnt.size(); i++){ 
    Scalar green_drawRecAndCircColor = Scalar(rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255)); 
    rectangle(green_drawRecAndCirc, green_boundRect[i].tl(), green_boundRect[i].br(), green_drawRecAndCircColor, 2, 8, 0); 
    //circle(green_drawRecAndCirc, green_center[i], (int)green_radius[i], green_drawRecAndCircColor, 2, 8, 0); 
} 
imwrite("c:\\testeimagem\\theeye\\resultados\\green_rectangle_and_circle.jpg", green_drawRecAndCirc); 

namedWindow("Green - Rectangle and Circle", CV_WINDOW_NORMAL); 
imshow("Green - Rectangle and Circle", green_drawRecAndCirc); 

/*Creating rectangles around the contours*/ 
//Yellow 
vector<vector<Point>>yellow_contours_poly(yellow_cnt.size()); 
vector<Rect>yellow_boundRect(yellow_cnt.size()); 
vector<Point2f>yellow_center(yellow_cnt.size()); 
vector<float>yellow_radius(yellow_cnt.size()); 

for (int i = 0; i < yellow_cnt.size(); i++){ 
    approxPolyDP(Mat(yellow_cnt[i]), yellow_contours_poly[i], 3, true); 
    yellow_boundRect[i] = boundingRect(Mat(yellow_cnt[i])); 
    minEnclosingCircle((Mat)yellow_contours_poly[i], yellow_center[i], yellow_radius[i]); 
} 

//Yellow - Draw polygonal contour AND bounding rects + circles 
Mat yellow_drawRecAndCirc = Mat::zeros(yellow.size(), CV_8UC3); 
for (int i = 0; i < yellow_cnt.size(); i++){ 
    Scalar yellow_drawRecAndCircColor = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); 
    rectangle(yellow_drawRecAndCirc, yellow_boundRect[i].tl(), yellow_boundRect[i].br(), yellow_drawRecAndCircColor, 2, 8, 0); 
    //circle(green_drawRecAndCirc, green_center[i], (int)green_radius[i], green_drawRecAndCircColor, 2, 8, 0); 
} 
waitKey(0); 
destroyAllWindows; 

return 0; 

Das Originalbild ist hier:

enter image description here

Und das Beispiel des Endergebnisses ist hier:

enter image description here

ich die Beispiele versuchte in den folgenden Link beschrieben (OpenCV Bounding Box), aber ich konnte es auch nicht funktionieren.


Edit 2:

Da ich einige Eigenschaften des Blattes finden muß, dass ich nicht mit einem Rechteck finden (wie Seitenverhältnis, mittlere Durchmesser, Radius-Verhältnis, Rundheit und bedeutet Feret) Ich musste den Ansatz ändern, das Blatt von einem Rechteck zu einer Ellipse zu finden. Die Sache ist, die Ellipse wird in das Blatt hineingezogen, um es zu konturieren.

Hier ist mein Code:

/*Load the image*/ 
Mat img_bgr = imread("image path", 1); 
if (img_bgr.empty()){ 
    cout << "No image found..." << endl; 
    return -1; 
} 

/*Conversion to HSV*/ 
Mat img_hsv; 
cvtColor(img_bgr, img_hsv, CV_BGR2HSV); 

/*Extracting colors - HSV*/ 
Mat yellow, green, brown; 

//Yellow 
inRange(img_hsv, Scalar(25, 80, 80), Scalar(36, 255, 255), yellow); 

//Green 
inRange(img_hsv, Scalar(37, 80, 80), Scalar(70, 255, 255), green); 

//Brown 
inRange(img_hsv, Scalar(10, 80, 80), Scalar(30, 200, 200), brown); 

// logical OR mask 
Mat1b mask = yellow | green | brown; 

// Find non zero pixels 
vector<Point> pts; 

findNonZero(mask, pts); 

// Compute ellipse 
RotatedRect elipse = fitEllipse(pts); 

//ELLIPSE - Heigth, Width and Center of Mass 
cout << "ELLIPSE:" << endl; 
cout << "\nHeight and Width: " << elipse.size; //Height and Width 
cout << "\nCenter of Mass: " << elipse.center << endl; //Center of mass (probably given in X and Y coordinates) 

// Show Ellipse 
ellipse(img_bgr, elipse, Scalar(0, 0, 255), 3); 
namedWindow("Ellipse", CV_WINDOW_NORMAL); 
imshow("Ellipse", img_bgr); 

waitKey(0); 
destroyAllWindows; 

return 0; 

Das Ergebnis ist unten dargestellt:

enter image description here

Ich kann nicht verstehen, was mache ich falsch, da ich nur den Code der Benutzer geändert Miki gab und das funktioniert eigentlich perfekt.

+1

Sie brauchen * "eine große Box, um sie alle zu regieren" * ... – karlphillip

+0

Hallo Karl. Ich sehe, dass Sie der Autor einer Lösung sind, die auf dem von mir geposteten Link erwähnt wird. Bitte zögern Sie nicht, Ihre Erfahrungen und Kenntnisse mit uns zu teilen. – Nicholas

Antwort

1

Da Ihr Bild recht einfach ist (Sie haben einen flachen Hintergrund), können Sie die Suche nach dem Blatt vereinfachen. Allerdings verwende ich Ihren Ansatz immer noch auf der Grundlage der Schwellenwerte der HSV-Werte, die im Allgemeinen wahrscheinlich robuster sind.


Um Breite und Höhe des Blattes zu finden, müssen Sie im Grunde seine Bounding Box finden. Sie müssen nicht alle Konturen Ihrer Farbmasken finden oder alle Begrenzungsrahmen zusammenführen.Aber Sie können:

1) berechnen die Maske für die gelben, grüne und braune Farben (I modifizieren sligthly die Bereiche sinnvolle Werte)

Gelb:

enter image description here

Grün:

enter image description here

Brown:

finden

enter image description here

2) oder dieser Maske toghether

enter image description here

3) alle Nicht-Null-Pixel 4) berechne die Begrenzungsbox

enter image description here

Code:

#include <opencv2/opencv.hpp> 
#include <vector> 
#include <string> 

using namespace std; 
using namespace cv; 

int main() 
{ 
    // Load the image 
    Mat3b img_bgr = imread("path_to_image"); 
    if (img_bgr.empty()){ 
     cout << "No image..." << endl; 
     return -1; 
    } 

    // Convert to hsv 
    Mat3b img_hsv; 
    cvtColor(img_bgr, img_hsv, COLOR_BGR2HSV); 

    Mat1b yellow, green, brown; 

    //Yellow 
    inRange(img_hsv, Scalar(25, 80, 80), Scalar(36, 255, 255), yellow); 
    //Green 
    inRange(img_hsv, Scalar(37, 80, 80), Scalar(70, 255, 255), green); 
    //Brown 
    inRange(img_hsv, Scalar(10, 80, 80), Scalar(30, 200, 200), brown); 

    // logical OR mask 
    Mat1b mask = yellow | green | brown; 

    // Find non zero pixels 
    vector<Point> pts; 
    findNonZero(mask, pts); 

    // Compute bounding box 
    Rect box = boundingRect(pts); 

    cout << "Width: " << box.width; 
    cout << "Height: " << box.height << endl; 

    // Show box 
    rectangle(img_bgr, box, Scalar(0,0,255), 3); 
    imshow("Box", img_bgr); 

    return 0; 
} 
+0

Können Sie mir bitte sagen, wie Sie die Breite und Höhe des Blattes bekommen? –

+0

druckt einige mehrstellige Nummer –

+0

Es ist am Ende des Codes, wie Miki demonstriert: '// Compute Bounding Box Rect Box = BoundingRect (PTS); cout << "Breite:" << box.width; cout << "Höhe:" << box.height << endl; // Zeige Box Rechteck (img_bgr, Box, Skalar (0,0,255), 3); imshow ("Box", img_bgr); ' – Nicholas