...primero debes detectar los bordes salientes...
Esto es:
- Recorre la imagen horizontalmente bajando hasta tocar el primer píxel, luego ídem pero desde abajo hacia arriba.
- Recorre la imagen verticalmente avanzando a la derecha hasta que toques el primer píxel, luego ídem pero desde la derecha y avanzando hacia la izquierda...
La forma más exacta, es resaltar los vértices salientes... Imagina que con un lápiz trazas líneas para encerrar cada figura en un polígono, pero siempre con ángulos convexos ('reentrantes', nunca cóncavos hacia afuera) y siempre tocando la figura, por supuesto.
Mediante la comparación luego de:
A - La superficie interna del polígono. buen candidato para determinar rápidamente los similares (pero no óptimo si varían en tamaño)
B - La cantidad de lados del polígono resultante. Buen candidato para a primera vista determinar similitud incluso entre diferentes tamaños.
C - Los ángulos que forman cada par de lados del polígono. Es la tarea final, las previas son aproximaciones rápidas.
Y con esto es relativamente asequible determinar su similitud con un porcentaje.
Éste algoritmo sería el adecuado, si además las formas tienen diferente tamaño (dos figuras iguales o muy parecidas pero de diferente tamaño), ya que los ángulos se mantienen así como el número de lados del polígono.
Basicamente en pseudocódigo son estos pasos:
Esta sería la función principal (tras los pasos que llevas)
Aquí el pseudocódigo para crear un polígono de cada imagen (a grandes rasgos).
Tu primer paso será entonces un "localizador de puntos salientes" de la figura...
El segundo, será un "trazador de líneas"... primero empezamos con los 4 puntos (uno de cada orientación, se trata de intentar lanzar una línea de uno de ellos al del lado contiguo, si corta en algún punto la figura, se debe buscar otro punto saliente entre medias y repetir).
Es mejor usar una lista que un array porque no se sabe cuanto se va a almacenar.
También puedes buscar similitud por perímetro cuando el número de lados es desigual. Si la superficie y el perímetro son similares hay probabilidades.
Tolerancia debe ser un valor en el rango 1-100, pero si se pone 100 exige exactitud total, y si se pone 1, una casa será igual que un coche, un valor adecuado podría ser 90% es decir uno es similar a otro si es un 90% del área (esto es solo varía un 10%, no confundir ambos valores, pués puede hacerse al derecho o al revés).
Se traza una línea ente los puntos extremos, y considerando el centro, se ve si p2, a que lado queda
respecto de la línea, según el centro debe quedar en un sitio u otro para saber si es cóncavo o convexo.
Crea una lista con los ángulos del polígono.
Aumento una de las figuras y realizo un pequeño dibujo a mano alzada. Nota el número de lados del polígono que encierra la figura, sus ángulos, etc... así te formas una idea y con esto debiera valerte... aunque tienes trabajo por delante...
Esto es:
- Recorre la imagen horizontalmente bajando hasta tocar el primer píxel, luego ídem pero desde abajo hacia arriba.
- Recorre la imagen verticalmente avanzando a la derecha hasta que toques el primer píxel, luego ídem pero desde la derecha y avanzando hacia la izquierda...
La forma más exacta, es resaltar los vértices salientes... Imagina que con un lápiz trazas líneas para encerrar cada figura en un polígono, pero siempre con ángulos convexos ('reentrantes', nunca cóncavos hacia afuera) y siempre tocando la figura, por supuesto.
Mediante la comparación luego de:
A - La superficie interna del polígono. buen candidato para determinar rápidamente los similares (pero no óptimo si varían en tamaño)
B - La cantidad de lados del polígono resultante. Buen candidato para a primera vista determinar similitud incluso entre diferentes tamaños.
C - Los ángulos que forman cada par de lados del polígono. Es la tarea final, las previas son aproximaciones rápidas.
Y con esto es relativamente asequible determinar su similitud con un porcentaje.
Éste algoritmo sería el adecuado, si además las formas tienen diferente tamaño (dos figuras iguales o muy parecidas pero de diferente tamaño), ya que los ángulos se mantienen así como el número de lados del polígono.
Basicamente en pseudocódigo son estos pasos:
Esta sería la función principal (tras los pasos que llevas)
Código [Seleccionar]
Buleano = Funcion Buscarsimilitudes(Lista de Imagenes Figuras )
Lista Poligonos // lista de poligono
Lista Poligono // lista de líneas
Por cada figura en Figuras
Poligono = CrearPoligono(figura)
Poligonos.Add (Poligono)
Siguiente
Bucle para j desde 0 Poligonos.Length -2 //el último se debe comparar
Poligono = Poligonos.Item(j)
Bucle para k desde j a Poligonos.Length -1
Si EsSimilar(Poligono, Poligonos.Item(k)) luego
// Mostrar coincidencia en la forma que tengas previsto.
Similares = TRUE
Fin si
Siguiente
Siguiente
Devolver Similares //si al menos hubo 2 similares entre sí, devolverá TRUE.
Fin Funcion
Aquí el pseudocódigo para crear un polígono de cada imagen (a grandes rasgos).
Tu primer paso será entonces un "localizador de puntos salientes" de la figura...
El segundo, será un "trazador de líneas"... primero empezamos con los 4 puntos (uno de cada orientación, se trata de intentar lanzar una línea de uno de ellos al del lado contiguo, si corta en algún punto la figura, se debe buscar otro punto saliente entre medias y repetir).
Es mejor usar una lista que un array porque no se sabe cuanto se va a almacenar.
Código [Seleccionar]
Lista = Funcion CrearPoligono(imagen Figura)
Lista Puntos //donde señaden los puntos.
Lista Poligono //donde se añaden las líneas
entero j, k
punto centro
centro = PuntoCentral(Figura) // se trata de hallar aprox, el punto central de la imagen, un eje de cordenadas en el centro.
Puntos = BuscarLos4PuntosMásSalientes // (de las 4 orientaciones), da igual si prefieres buscarlos en diagonal, pero es más complejo recorrer así la imagen.
j=0
k=(j+1)
Hacer
Linea = TrazarLinea(puntos.Item(j), Puntos.Item(k) )
Si Linea CortaFigura(Linea, Figura) luego //Si la línea corta la figura...
Punto = Buscar nuevo punto saliente entre ambos, y añadir delante del destino
Puntos.Add(punto, k)
Sino
//OJO: No trato el caso de que k sea el último y el 3º punto debiera ser el primero el 0º
// queda a tu esfuerzo modificarlo como convenga...
Si AnguloEsConcavo(puntos.Item(j), Puntos.Item(k), Puntos.Item(k+1), centro ) = FALSE luego
Poligono.Add(Linea)
j = k
Si (k < Puntos.Count) luego
k +=1
Sino
Si (k=0) luego
Conectado = TRUE
Sino
k = 0
Fin si
Fin si
Sino
El punto intermedio entre los dos se elimina // hace concavidad, la búsqueda (la programación) del más saliente no fue 'adecuada', pero bueno esto nos permite avanzar aunque sea más lentamente.
// j y k no cambian, así al retorno se traza la línea entre esos dos (que antes tenían uno en medio).
Fin si
Fin si
Repetir Mientras (Conectado= FALSE)
Devolver Poligono
Fin funcion
También puedes buscar similitud por perímetro cuando el número de lados es desigual. Si la superficie y el perímetro son similares hay probabilidades.
Código [Seleccionar]
Buleano = EsSimilar(Lista p1, Lista p2) // p1 y p2 son sendos polígonos
Area1 = HallarArea(p1)
Area2 = HallarArea(p2)
Si SimilitudPorTolerancia(Area1, Area2, ToleranciaArea) = TRUE luego //tolerancia debe expresarse en forma de porcentaje aceptable, p.e.: '90' por ciento.
// son de tamaño similar, no hay zoom, o es escaso.
Si SimilitudAngulos(p1, p2, ToleranciaAngulos) = TRUE luego
Devolver TRUE
Fin si
Sino // son distintos, puede que uno esté con zoom... comprobamos lados y angulos
// comprobamos la similitud en el número de lados.
Si SimilitudPorTolerancia(p1.Length, p2.Length, ToleranciaLados) = TRUE luego
Si SimilitudAngulos(p1, p2, ToleranciaAngulos) = TRUE luego
Devolver TRUE
Fin si
Si no
// El número de lados si no cincide ver si hay o falta un lado de tamaño muy corto, pero no se expone aquí...
// Si cambia el númeor de lados, vamos a exigir más exactitud, con los ángulos
Si SimilitudAngulos(p1, p2, ToleranciaAngulos+ToleranciaExigente) = TRUE luego
Devolver TRUE
Fin si
Fin si
Fin si
Fin Funcion
Tolerancia debe ser un valor en el rango 1-100, pero si se pone 100 exige exactitud total, y si se pone 1, una casa será igual que un coche, un valor adecuado podría ser 90% es decir uno es similar a otro si es un 90% del área (esto es solo varía un 10%, no confundir ambos valores, pués puede hacerse al derecho o al revés).
Código [Seleccionar]
Buleano = Funcion SimilitudPorTolerancia(entero v1, entero v2, byte Tolerancia)
Si (v1 >= v2) luego //
Si (((v1/100) * Tolerancia) >= v2) luego Devolver TRUE
Sino
Si (((v2/100) * Tolerancia) >= v1) luego Devolver TRUE
Fin si
Fin Funcion
Se traza una línea ente los puntos extremos, y considerando el centro, se ve si p2, a que lado queda
respecto de la línea, según el centro debe quedar en un sitio u otro para saber si es cóncavo o convexo.
Código [Seleccionar]
Buleano = Funcion AnguloEsConcavo(Punto p1, Punto p2, Punto p3, Punto centro)
Linea
Linea = TrazarLínea(p1,p3) //Trazar una línea desde p1 a p3
//Ver donde queda p2 respecto de la linea y según p1 y p3 estén orientados respecto del centro
Si p1.X < centro.x
// Sin terminar... queda a tu esfuerzo
Sino
// Sin terminar... queda a tu esfuerzo
Fin si
Fin Funcion
Código [Seleccionar]
Buleano = Funcion SimilitudAngulos(Poligono pol1, Poligono pol2)
Lista Angs1, Angs2
Decimal ang1, ang2 //valor en coma flotante
Buleano Similares
Angs1 = AngulosPoligono(pol1)
Angs2 = AngulosPoligono(pol2)
// Quizás una figura esté rotada respecto de otra, luego exige encontrar ekl punto de coincidencia.
// pero puede pasar que haya más de un ángulo en una figura que tenga el mismo que otro en la otra figura...
Bucle para i desde 0 a Angs1.Length
ang1 = Angs1.Item(i)
Bucle para cada j desde 0 a Angs2.length
ang2 = Angs1.Item(j)
// se convierten a enteros, tal como exige la función...
Si SimilitudPorTolerancia(ConvertirAEntero(ang1), ConvertirAEntero(ang2), ToleranciaAngulo) = TRUE luego
Similares = TRUE
Bucle para k desde j+1 a Angs1.Length
ang2 = Angs1.Item(k)
Si SimilitudPorTolerancia(ConvertirAEntero(ang1), ConvertirAEntero(ang2), ToleranciaAngulo) = False luego
Similares = FALSE
Salir del bucle
Fin si
Fin Bucle
Si (Similares = TRUE) luego Devolver TRUE
Fin si
Fin bucle
Fin Bucle
Fin Funcion
Crea una lista con los ángulos del polígono.
Código [Seleccionar]
Lista = Funcion AngulosPoligono(Poligono Pol)
Lista Angulos
Punto p1, p2, p3
p1 = pol1.Item(0)
p2 = pol1.Item(1)
p3 = pol1.Item(2)
Angulo = AnguloFormado3Pt(p1, p2, p3)
Angulos.Add(angulo)
Bucle para j desde 3 a p1.Length - 1 // si es un triángulo, no entrará en el bucle
p1=p2
p2=p3
p3= pol1.Item(j)
Angulo = AnguloFormado3Pt(p1, p2, p3)
Angulos.Add(angulo)
Fin bucle
// Faltan 2 ángulos, los formados por el final y el comienzo
p1=p2
p2=p3
p3= pol1.Item(0)
Angulo = AnguloFormado3Pt(p1, p2, p3)
Angulos.Add(angulo)
p1=p2
p2=p3
p3= pol1.Item(1)
Angulo = AnguloFormado3Pt(p1, p2, p3)
Angulos.Add(angulo)
Devolver Angulos
Fin Funcion
Código [Seleccionar]
Decimal = AnguloFormado3Pt(Punto p1, Punto p2, Punto p3)
// queda a tu esfuerzo, son simples matemáticas...
Fin funcion
Aumento una de las figuras y realizo un pequeño dibujo a mano alzada. Nota el número de lados del polígono que encierra la figura, sus ángulos, etc... así te formas una idea y con esto debiera valerte... aunque tienes trabajo por delante...
