2012-06-26 6 views
6

In meinem Projekt möchte ich die Größe aus dem größten homogenen Bereich einer bestimmten Farbe erhalten (in meinem Beispiel ist es der blaue Himmel).Wie bekomme ich die Größe einer Fläche in JavaCV?

Meine erste Idee ist das ursprüngliche Bild zu konvertieren:

original image

auf ein binäres Bild, das Skycolor zu erkennen und eine Maske mit diesem Bereich zu erstellen: mask image

Aber wie kann ich die Größe und die Position dieser weißen Pixel? Ich möchte eine effiziente Methode, die stimmt, wenn das Bild im oberen Drittel des Bildes einen blauen Himmel hat. Irgendwelche Ideen? Soll ich eine "globale Maske" erstellen (siehe Bild 3 im Kommentar) und mit dem Binärbild vergleichen? Oder gibt es einen leichteren Weg?

Vielen Dank.

+0

ein neuer Benutzer kann nur 2 Links hinzufügen:/hier ist die Maske ich denke, mit dem zweiten Bild zu vergleichen [siehe Bild 3] (http://img441.imageshack.us/img441/8231/maskt.jpg) –

+0

Möchten Sie blaue Farbe oder Farbe mit größtem Quadrat erkennen? – ArtemStorozhuk

+0

Ich möchte die Größe und die Position des größten Quadrats/Fläche, die blaue Farbe haben –

Antwort

6

Der Algorithmus ist folgende:

  1. Konvertieren Eingangsbild zu YCbCr color space der blau zu erkennen ist gut (und auch rot) Farbe: YCrCb image Um etwas Bild auf einem anderen cvtColor Verwendung Farbraum zu konvertieren.
  2. Blaukanal daraus extrahieren: Blue image Verwenden Sie die Funktion extractChannel, um den benötigten Kanal zu extrahieren.
  3. Bereiche mit dem größten Wert [0-255] der blauen Farbe erkennen. Ich habe die Funktion minMaxIdx verwendet und dann die maximale Multiplikation mit 0.8 (dies ist der Schwellenwert). Sie können komplexere Methoden wie die Histogrammanalyse verwenden.
  4. Machen Sie eine Maske der blauen Farbe: binary Dafür verwendete ich threshold Funktion mit in Schritt 3 berechnet Schwelle (als Parameter).
  5. Finden Sie alle blauen Konturen in der Maske. In OpenCV ist es einfach - verwenden Sie einfach findContours.
  6. Und schließlich erkennen Kontur mit größten Quadrat und finden Sie seine Koordinaten (Mitte). Um die Kontur mit dem größten Quadrat zu berechnen, können Sie die Funktion contourArea verwenden.

auch anstelle der Schritte 1-4 Sie Bild zu HSV umwandeln kann und inRange blaue Farbe erkennen verwenden.

Hier ist mein C++ impementation:

Mat inMat = imread("input.jpg"), blueMat, threshMat; 

cvtColor(inMat, blueMat, CV_BGR2YCrCb);//convert to YCrCb color space 

extractChannel(blueMat, blueMat, 2);//get blue channel 

//find max value of blue color 
//or you can use histograms 
//or more complex mathod 
double blueMax; 
minMaxIdx(blueMat, 0, &blueMax); 

blueMax *= 0.8; 
//make binary mask 
threshold(blueMat, threshMat, blueMax, 255, THRESH_BINARY); 

//finding all blue contours: 
vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
findContours(blueMat, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 

double maxSquare = 0; 
vector<Point> maxContour; 
//finding contours with biggest square: 
for (size_t i=0; i<contours.size(); i++) 
{ 
    double square = contourArea(contours[i]); 
    if (square > maxSquare) 
    { 
     maxContour = contours[i]; 
     maxSquare = square; 
    } 
} 

//output results: 
Point center = centerPolygon(maxContour); 
cout << "square = " << maxSquare << endl; 
cout << "position: x: " << center.x << ", y: " << center.y << endl; 

Hier centerPolygon Funktion:

Point centerPolygon(const vector<Point>& points) 
{ 
    int x=0, y=0; 

    for (size_t i=0; i<points.size(); i++) 
    { 
     x += points[i].x; 
     y += points[i].y; 
    } 

    return Point(x/points.size(), y/points.size()); 
} 

Die Ausgabe des Programms ist neben:

square = 263525 
position: x: 318, y: 208 

Sie diesen Code umwandeln kann JavaCV - siehe this tutorial.

+0

hey, danke! :) Ich werde es morgen versuchen :) –

+0

@destiny nicht mir dafür danken - nur +1 oder Akzeptant Antwort. Siehe [Handbuch] (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). – ArtemStorozhuk

+0

jey, jetzt funktioniert es gut für mich :) Aber warum nimmst du YCbCr? Die ganze Zeit dachte ich, dass LAB das Beste ist, Farben zu erkennen PS: Ich kann nur +1 treffen, dann habe ich 15 Ruf. –