En esta semana se nos encargo detectar las esquinas de los polígonos en la imagen.
La parte básica: detectar las esquinas con el método de diferencia de filtro mediano y ya la parte avanzada: teniendo las esquinas, podemos sacar un “wire-frame” al borde.
En base a las esquinas que se detectaran y mediante sus bordes, y esas esquinas se unen con segmentos de lineas rectas recorriendolas en un orden que sigue el borde.
Detección de esquinas con un filtro mediano
• Calcular una versión con filtro de mediano de la imagen original.
• Sacar la diferencia entre la imagen original y el resultado del filtro.
• El chiste es primero disminuir el ruido en la imagen.
• Por ejemplo eliminando ruido tipo sal-pimienta.
• Evita que pixeles que son ruido se resalten como esquinas.
Estas son algunas imágenes utilizadas de prueba
Aquí pueden observarse las esquinas de las dos figuras ,como se puede observar el circulo es omitido ya que no contiene esquinas.
Ahora se procede arealizar un recorrido "wire-frame" , este tipo de métodos ya fue usado en tareas pasadas para sacar los bordes y como estas esquinas están dentro de ellas nos son de mucha utilizad para sacar los puntos X, Y donde se encuentran y aplicamos un recorrido bfs.
Después de todos los pasos estos son los resultados.
Aquí dejo el código relevante.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sys import argv, exit | |
from os import path | |
import Image, ImageDraw | |
import math | |
def convolucion(image,gResultant): | |
ancho, altura = image.size | |
pixeles = image.load() | |
imageN = Image.new('RGB', (ancho,altura)) | |
pixels = imageN.load() | |
for x in range(ancho): | |
for y in range(altura): | |
sumatoria = 0 | |
for i in range(x-1, x+2): | |
for j in range(y-1, y+2): | |
try: | |
sumatoria += gResultant[i - (x-1)][j - (y-1)] * pixeles[i,j][1] | |
except: | |
pass | |
pixels[x,y] = (sumatoria,sumatoria,sumatoria) | |
image.save('salidaB.png', "png") | |
return imageN | |
def bfs(image, origen, color): | |
pixeles = image.load() | |
ancho,altura = image.size | |
cola = [] | |
coordenadas = [] | |
cola.append(origen) | |
original = pixeles[origen] | |
while len(cola) > 0: | |
(x, y) = cola.pop(0) | |
actual = pixeles[x, y] | |
if actual == original or actual == color: | |
for dx in [-1, 0, 1]: | |
for dy in [-1, 0, 1]: | |
i, j = (x + dx, y + dy) | |
if i >= 0 and i < ancho and j >= 0 and j < altura: | |
contenido = pixeles[i, j] | |
if contenido == original: | |
pixeles[i, j] = color | |
coordenadas.append((i, j)) | |
cola.append((i, j)) | |
image.save('output.png', 'png') | |
return len(coordenadas), coordenadas | |
def normalizar(image, maximovalor): | |
pixeles = image.load() | |
umb = 255.0/maximovalor | |
for x in range(image.size[0]): | |
for y in range(image.size[1]): | |
pixeles[x, y] = int(pixeles[x, y]*umb) | |
return image | |
def binarizar(image, umbral): | |
ancho, altura = im.size | |
pixeles = image.load() | |
salida = Image.new('RGB', (w, h)) | |
salidapixeles = out.load() | |
for i in range(ancho): | |
for j in range(altura): | |
r, g, b = pixeles[i, j] | |
if r > umbral: | |
salidapixeles[i, j] = (255, 255, 255) | |
else: | |
salidapixeles[i, j] = (0, 0, 0) | |
out.save('salida_binarizada.png', 'PNG') | |
return out | |
def difuminar(image, n): | |
ancho, altura = image.size | |
pixeles = image.load() | |
imagens = Image.new("RGB", (ancho, altura)) | |
pixelessalida = imagens.load() | |
promedio = [] | |
for N in range(n): | |
for anch in range(ancho): | |
for alto in range(altura): | |
promedio = [] | |
promedio.append(list(pixeles[anch, alto])) | |
if anch> 0: | |
promedio.append(list(pixeles[anch-1, alto])) | |
if anch < ancho-1: | |
promedui.append(list(pixeles[anch+1, alto])) | |
if alto < altura-1: | |
promedui.append(list(pixeles[anch, alto+1])) | |
if alto > 0: | |
promedio.append(list(pixeles[anch, alto-1])) | |
sumatota = [ sum(x) for x in zip(*promedio) ] | |
r=sumatota[0]/len(promedio) | |
g=sumatota[1]/len(promedio) | |
b=sumatota[2]/len(promedio | |
pixelessalida[anch, alto] = (r,g,b) | |
imagens.save('salidavecind.png', "png") | |
return imagens | |
def Restaimagen(imagen, imagen2): | |
ancho, altura = imagen.size | |
pixeles = imagen.load() | |
pixeless = imagen2.load() | |
imagesal = Image.new('RGB', (ancho, altura)) | |
matriz = imagesal.load() | |
for i in range(ancho): | |
for j in range(altura): | |
vistacolor = [] | |
for w in range(3): | |
vistacolor.append(pixeles[i, j][w] - pixeless[i, j][w]) | |
matriz[i, j] = tuple(vistacolor) | |
imagesal.save('salida.png') | |
return imagesal | |
def SaMe(pixeles): | |
pixelescol = [list(x) for x in zip(*pixeles)] | |
M = [] | |
for vista in pixelescol: | |
vista.sort() | |
M.append(vista[len(vista)/2]) | |
return M | |
def mediano(image, tamano): | |
pixeles = image.load() | |
ancho,altura = image.size | |
largo1 = len(tamano) | |
largo2 = len(tamano[0]) | |
tamano = (5,5) | |
pixnuev= im.load() | |
salidafiltro = Image.new('RGB', (ancho, altura)) | |
pixeles = salidafiltro.load() | |
largototx = [n for n in range(-largo1/2 + 1, largo1/2 + 1)] | |
largototy = [n for n in range(-largo2/2 + 1, largo2/2 + 1)] | |
for i in range(ancho): | |
for j in range(altura): | |
pixeless = [] | |
for x in largototx: | |
for y in largototy: | |
enx = i + x | |
eny = j + y | |
if enx >= 0 and enx < ancho and eny >= 0 and eny < altura: | |
pixeless.append(pixnuev[enx, eny]) | |
mno = SaMe(pixeless) | |
pixeles[i, j] = tuple(mno) | |
salidafiltro.save('salidafiltromediano.png', 'PNG') | |
return salidafiltro | |
Por alguna razón algunas veces el punto medio de la figura lo ponía equivocado
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
varTamanobolita=30 | |
promedio = (figura[0]*var[0] / len(figura[i]), promedio[1]*var[1] / len(figura[i])) | |
for i in range(len(figura)): | |
for j in range(len(figura[i])): | |
x = figura[i][j][0]*var[0] | |
y = figura[i][j][1]*var[1] | |
draw.text((x, y), str(j+1), fill=(0, 0, 255), font=font) | |
draw.ellipse((promedio[0]-varTamanobolita, promedio[1]-varTamanobolita, prom[0]+varTamanobolita, promedio[1]+varTamanobolita), fill=(0, 0, 0)) | |
draw.text((promedio[0]+10, promedio[1]), 'figura # '+str(i+1), fill=(0, 255, 255), font=font) | |
print 'figura numero '+str(i+1), 'numero de lados =', str(len(figura[i])) | |
Creo que se en esta parte se podría hacer alguna condición que si la imagen es de mas grande de tantos pixeles , se cambie automáticamente el tamaño de la letra y del centro porque aveces era muy grande como el ejemplo de arriba y apenas se alcanzaba a distinguir y tenia que mover manualmente al tamaño.
Si hubieras asistido clase o lab, sabrías que el wire-frame no era regresar el borde de la imagen original sino unir los puntos con segmentos de rectas. 7 pts.
ResponderEliminar