2012-08-28 26 views
10

Estoy trabajando en una aplicación de reconocimiento de formas. En este momento, un conjunto de puntos (x, y) está determinado por el detector de esquina (puntos rojos, img. 2). Cuatro de estos puntos (en marcos rojos, img. 2.) Son vértices de un rectángulo (a veces un pequeño rectángulo deformado). ¿Cuál sería la mejor manera de encontrarlos entre otros?Cómo comprobar si cuatro puntos forman un rectángulo

Aquí es un ejemplo de una imagen de entrada: Input image

y parece que esto después de la detección de la esquina:

Image with detected corners

Respuesta

11

Esta no es una respuesta a su pregunta, solo es una sugerencia.

En mi opinión, el detector de esquina es una mala forma de detectar rectángulos; llevará mucho tiempo calcular todas las distancias de puntos como mathematician1975 sugerido. Debe utilizar otra técnica en esta situación:

  1. Ese sello es de color violeta, por lo que lo primero que debe hacer es segmentar el color.
  2. Después de que haya terminado con paso 1 puede usar Houhg transform para detectar líneas en la imagen binaria. O encuentre todos los contornos en la imagen.
  3. Y el último paso es detectar el rectángulo.

Actualización:

Aquí hay otra solución que debería funcionar también en imágenes en gris.

  1. Haz un umbral para convertir una imagen de 1 bit (utilicé de 255 como umbral).
  2. Encuentra todos los contornos en la nueva imagen que tienen un área más grande que alguna constante (tomé).
  3. Encuentra rectángulo que bordea para cada contorno y hacer una verificación:

ContourArea/BoundingReactangleArea> constante

Aprovecho esta constant como 0,9.

Y este algoritmo me dio resultado siguiente: enter image description here

Aquí es código de OpenCV:

Mat src = imread("input.jpg"), gray, result; 
vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 

result = Mat(src.size(), CV_8UC1); 

cvtColor(src, src, CV_BGR2GRAY); 
threshold(src, gray, 200, 255, THRESH_BINARY_INV); 
findContours(gray, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 

result = Scalar::all(0); 
for (size_t i=0; i<contours.size(); i++) 
{ 
    Rect rect = boundingRect(contours[i]); 
    if (rect.area() > 1000) 
    { 
     double area = contourArea(contours[i]); 
     if (area/rect.area() > 0.9) 
     { 
      drawContours(result, contours, i, Scalar(255), -1); 
     } 
    } 
} 
+0

Sí, como señaló el cálculo de todas las distancias consume mucho tiempo, incluso para _small_ imagen de entrada. Ya he comprobado esa solución. Segmentación del color no sería útil con las imágenes en escala de grises (los ejemplos son un poco confusos, lo siento) pero lo usé para los RGB. En cuanto a la transformada de Hough Hice algunas pruebas y funciona bastante bien, pero las líneas detectadas ** ** hacerlo no se cruza con otra como se muestra aquí: [Hough] (http://i.imgur.com/NP8HT .jpg). – sowizz

+0

@sowizz mira la actualización. – ArtemStorozhuk

+0

Esto funciona bastante bien en la mayoría de los casos, así que lo voy a marcar como respuesta. Sin embargo, en algunas situaciones falla porque no hay un área cerrada. Las operaciones morfológicas son útiles entonces, pero para casi cada caso necesitan diferentes parámetros, lo que los hace no tan útiles. ¿Alguna idea de cómo resolver ese problema? Aquí hay un ejemplo de tal situación: [click] (http://i.imgur.com/mY27w.jpg) – sowizz

9

Calcular el conjunto de 6 longitudes que va a tener entre cada par de 4 puntos distintos Dentro de ese conjunto de 6 longitudes si hay más de 3 valores distintos, no tiene un rectángulo (2 longitudes de lados iguales más longitudes diagonales iguales)

+3

con algunas tolerancias aplicadas, o curso –

+0

@RodyOldenhuis, por supuesto. – mathematician1975

+0

Buena solución, pero no realmente útil en este problema exacto. Cálculo de todas las distancias lleva mucho tiempo, incluso si hay 100 puntos y suelo obtener alrededor de 2500. – sowizz

0

Considera que debería haber conseguido el número 8 pero se obtuvo el número 7, entonces usted va a agregar el número de 1 (llamado delta o corrección de errores) para corregirlo.

De manera similar, tenga un delta de coordenadas rectangulares para corregir el rectángulo. Verifique que el punto (coordenada) esté dentro del rectángulo delta.

Las coordenadas del rectángulo son como se mencionan a continuación:

x+delta,y+delta 
x-delta,y+delta 
x+delta,y-delta 
x-delta,y-delta 

Vamos a saber si esto funciona bien para usted o si usted encuentra una solución mejor

2

Usted es consciente de que mediante la inspección visual del punto de enturbiamiento se ya se puede distinguir una multitud de rectángulos? En otras palabras, es probable que encuentre muchos rectángulos si no hace una especie de rutina de preselección ...

De todos modos, aparte del método ya proporcionado por @ mathematician1975, también puede comprobar si los lados son (más o menos) paralelos.

Llamemos al método @ mathematician1975 method 1 y verifique en paralelo method 2. Entonces :

%# method 1: 
n1 = |u1-u2| %# 3 sub., 3 mult, 2 add. per distance 
n2 = |u3-u2| %# total of 6 distances to compute. 
n3 = |u4-u3| %# then max 5+4+3+2+1 = 15 comp. to find unique distances 
n4 = |u1-u4|  
n5 = |u4-u2| %# Total: 
n6 = |u3-u1| %# 12 sub., 18 mult., 12 add, 15 comp 



%# method 2: 
w1 = u1-u2  %# 3 subtractions per vector 
w2 = u3-u2  %# total of 4 vectors to compute 
w3 = u3-u2 
w4 = u1-u4     
         %# 12 sub. 
abs(w1-w3) == [0 0 0] %# 3 sub., 3 comp., 1 sign. 
abs(w2-w4) == [0 0 0] %# 3 sub., 3 comp., 1 sign. 

         %# Total: 18 sub., 6 comp. 2 sign. 

Tenga en cuenta que estos son tanto peor de los casos; con un poco de contabilidad puede reducir drásticamente el costo de ambos.

Tenga en cuenta también que method 2 necesita saber de antemano que los vértices ya están en el orden correcto. Si este no es el caso, aumentará el costo por un factor de 4, que es más que method 1..

¿Puedo preguntar cómo está calculando las distancias?

+0

Sí, sé que tener esa cantidad de puntos formará una gran cantidad de rectángulos, pero no estoy seguro de si hay algo que pueda hacer al respecto en esta etapa (más adelante calcularé algunas estadísticas que me permitirían elegir solo las adecuadas) rectángulos). La distancia entre dos puntos se calcula como distancia euclidiana: 'distance = sqrt ((x2-x1)^2 + (y2-y1)^2);' y no estoy seguro si es 2500x4, porque tiene que elegir un punto, luego otro 3, calcular las distancias, luego, para el mismo punto de puño, elige otros 3 puntos (diferentes a los anteriores) que van mucho más allá de las combinaciones de 2500x4. – sowizz

+1

@sowizz Prueba 'norma' - debería ser mucho más rápido. O, si lo desea, simplemente omita la raíz cuadrada: no importa la comparación de la distancia al cuadrado o la distancia. O bien, use las distancias de bloque de ciudad: 'abs (x2-x1) + abs (y2-y1)'. Esto dará una aproximación muy aproximada, pero * mucho más rápida * a la distancia, que, en el caso de un rectángulo, también tendrá que ser igual. –

Cuestiones relacionadas