2012-06-26 10 views
6

En mi proyecto, quiero obtener el tamaño del área homogénea más grande de un color específico (en mi ejemplo a continuación es el cielo azul).Cómo obtener el tamaño de un área en JavaCV

Mi primera idea es convertir la imagen original:

original image

a una imagen binaria, detectar la skyColor y crear una máscara con esta área: mask image

Pero, ¿cómo puedo conseguir el tamaño y la posición de estos píxeles blancos? Quiero un método eficiente, que dice verdadero, si la imagen tiene un cielo azul en el tercio superior de la imagen. Alguna idea? ¿Debería crear una "máscara global" (ver la imagen 3 en el comentario) y compararla con la imagen binaria? ¿O hay una forma más fácil?

Gracias.

+0

un nuevo usuario solo puede agregar 2 enlaces:/aquí está la máscara, creo que para compararla con la segunda imagen [ver imagen 3] (http://img441.imageshack.us/img441/8231/maskt.jpg) –

+0

¿Quieres detectar el color azul o el color con el cuadrado más grande? – ArtemStorozhuk

+0

quiero el tamaño y la posición del cuadrado/área más grande que tienen el color azul –

Respuesta

6

El algoritmo es el siguiente:

  1. convertir una imagen de entrada a YCbCr color space lo cual es bueno para detectar azul (y también rojo): YCrCb image Convertir alguna imagen a otro espacio de color uso cvtColor.
  2. Extraiga el canal azul de él: Blue image Utilice la función extractChannel para extraer el canal necesario.
  3. Detecta regiones con mayor valor [0-255] de color azul. Usé la función minMaxIdx y luego multipliqué el máximo en 0.8 (este es el umbral). Puede usar métodos más complejos como el análisis de histogramas.
  4. Haga una máscara de color azul: binary Para esto utilicé la función threshold calculada en el umbral del paso 3 (como parámetro).
  5. Encuentra todos los contornos azules en la máscara. En OpenCV es fácil: solo use findContours.
  6. Y, finalmente, detectar el contorno con el cuadrado más grande y encontrar sus coordenadas (centro). Para calcular el contorno con el cuadrado más grande puede usar la función contourArea.

También en lugar de pasos 1-4 que puede convertir la imagen a HSV y el uso de inRange detectar el color azul.

Aquí es mi 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; 

Aquí es centerPolygon función:

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

La salida del programa es el siguiente:

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

usted puede convertir el código de JavaCV - Ver this tutorial.

+0

¡oye, gracias! :) Lo intentaré mañana :) –

+0

@destiny no me agradezcas eso - solo presiona +1 o acepta respuesta. Ver [manual] (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). – ArtemStorozhuk

+0

jey, ahora funciona muy bien para mí :) Pero, ¿por qué tomas YCbCr? Todo el tiempo pensé que LAB es lo mejor para detectar colores PS: puedo golpear +1 solo entonces tengo 15 reputaciones. –

Cuestiones relacionadas