Aplicar una máscara de convolución consiste en utilizar una matriz, comúnmente de 3x3 creada o determinada por matemáticos o personas dedicadas al filtrado de imágenes, para aplicarla en los pixeles de una imagen. El proceso consiste en tomar un pixel para utilizar sus vecinos y de esta manera colocar la matriz encima y provocar distintos filtros o cambios en la imagen.
Pueden consultar estas páginas que me sirvieron de mucho para comprender este concepto:
Como primer prueba utilicé un filtro Gaussiano, que es el siguiente:
Y como resultado obtuve el efecto que se conoce como Blur o difuminado en escala de grises, esto tan solo como pruebas.
Lo que realicé fue tomar un pixel, sumar todos sus vecinos y multiplicar por la posición correspondiente a la matriz Gaussiana y el resultado colocarlo en el pixel. Ésta es la fórmula que seguí para esto:
Donde f(x,y) es el pixel de la imagen que se está tratando, g(x,y) es la posición en la máscara.
Aquí la rutina que utilicé para realizar esto. Cabe aclarar que cambié todo mi código ya que estoy leyendo un libro de Python y quise poner en práctica las clases y objetos en python.
def convolucion(self): pixeles = self.imActual.load() imCon = Image.new("L", (self.w, self.h)) conPix = imCon.load() h = [(0,0.2,0), (0.2,0.2,0.2), (0,0.2,0)] for x in range(self.h): for y in range(self.w): suma = 0 for i in range(3): for j in range (3): try: if x < self.w or y < self.h: suma += int(pixeles[(x-1)+i,(y-1)+j] * h[j][i]) except IndexError: suma += 0 #print suma conPix[x,y] = suma imCon.save('convolusion.png') self.imActual = imCon self.actualizarFondo()
El resultado obtenido es el siguiente:
Imagen Original:
Imagen con Convolución
Ahora para obtener los bordes de la imagen lo que utilicé fue una máscara o filtro sobel, el procedimiento que hice fue primero binarizar la imagen, después seguí el mismo procedimiento de la concolución con la máscara de Gauss pero para poder utilizar el filtro Sobel fue necesario cambiar el sentido de recorrer los pixeles de la imagen ya que de hacerlo ancho x largo la imagen la obtenía de manera invertida.
Este operador utiliza dos matrices para calcular las gradientes en x y en y para de esta manera determinar cuando hay un cambio de intensidad en los pixeles y así saber cuando es un borde
Este es el código para obtener los bordes:
def bordes(self): '''Aplica mascara Sobel para obtener los bordes de una imagen ''' tiempoIn = time.time() if self.imActual.mode == 'RGB': self.binarizar() pixeles = self.imActual.load() imBor = Image.new("L", (self.w, self.h)) borPix = imBor.load() gx = ([-1,0,1], [-2,0,2], [-1,0,1]) gy = (([1,2,1], [0,0,0], [-1,-2,-1])) for y in range(self.h): for x in range(self.w): sumaX = 0 sumaY = 0 for i in range(len( gx[0] )): for j in range(len( gy[0] )): try: resX = gx[i][j] * pixeles[x+j,y+i] resY = gy[i][j] * pixeles[x+j,y+i] except IndexError: resX = 0 resY = 0 sumaX = resX + sumaX sumaY = resY + sumaY cuadradosX = pow(sumaX,2) cuadradosY = pow(sumaY,2) g = int(math.sqrt(cuadradosX + cuadradosY)) suma = g if suma > 255: borPix[x,y] = 255 elif suma < 0: borPix[x,y] = 0 imBor.save('bordes.png') tiempoFin = time.time() print 'Mascara Sobel tardo: ', tiempoFin - tiempoIn, ' segundos' self.imActual = imBor self.actualizarFondo()
El resultado de aplicar este filtro es el siguiente:
Tiempo de procesamiento: 5.25 segundos
El resultado no es muy preciso con todas las imágenes como se puede apreciar en la imagen anterior, pero obtiene casi todos los bordes.
En promedio utilizando esta imagen a color y pasando por la binarización y el filtro Sobel, el tiempo de procesamiento fue de 5.25 segundos.
Otra prueba realizada:
Tiempo de procesamiento promedio: 6.56 segundos
La información de este filtro la pueden comprobar en Wikipedia que fue donde consulté
Aquí mi git con todo el código: git
OK; 5.
ReplyDelete