207 lines
4.8 KiB
Python
207 lines
4.8 KiB
Python
# ~*~ encoding: utf-8 ~*~ #
|
|
|
|
import random
|
|
import time
|
|
|
|
import sys
|
|
sys.path.append(sys.path[0]+'/..')
|
|
from BMPFile import RGBPixel
|
|
|
|
|
|
class Filter:
|
|
|
|
# Applique un filtre moyen à l'image de base vers l'image de sortie #
|
|
#####################################################################
|
|
# @param pixelMap Matrice de pixel à traiter (modifier)
|
|
# @param seuil Ecart entre le pixel et ses alentours à partir duquel on applique le lissage
|
|
#
|
|
#
|
|
# Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant :
|
|
#
|
|
# 1 1 1
|
|
# 1 1 1
|
|
# 1 1 1
|
|
#
|
|
def averageFilter(self, drawer, pixelMap):
|
|
return self.Convolution(drawer, pixelMap, kernel=[
|
|
[1, 1, 1],
|
|
[1, 1, 1],
|
|
[1, 1, 1]
|
|
] );
|
|
|
|
|
|
# Applique un filtre de Roberts à l'image de base vers l'image de sortie #
|
|
##########################################################################
|
|
# @param pixelMap Matrice de pixel à traiter (modifier)
|
|
#
|
|
#
|
|
# Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant :
|
|
#
|
|
# 1 0
|
|
# 0 -1
|
|
#
|
|
def Roberts(self, drawer, pixelMap):
|
|
return self.Convolution(drawer, pixelMap, kernel=[
|
|
[1, 0],
|
|
[0, -1]
|
|
] );
|
|
|
|
# Applique un filtre de Laplace à l'image de base vers l'image de sortie #
|
|
##########################################################################
|
|
# @param pixelMap Matrice de pixel à traiter (modifier)
|
|
#
|
|
#
|
|
# Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant :
|
|
#
|
|
# -1 -1 -1
|
|
# -1 8 -1
|
|
# -1 -1 -1
|
|
#
|
|
def Laplace(self, drawer, pixelMap):
|
|
return self.Convolution(drawer, pixelMap, kernel=[
|
|
[-1, -1, -1],
|
|
[-1, 8, -1],
|
|
[-1, -1, -1]
|
|
] );
|
|
|
|
|
|
# Applique un filtre de Sobel à l'image de base vers l'image de sortie #
|
|
########################################################################
|
|
# @param pixelMap Matrice de pixel à traiter (modifier)
|
|
#
|
|
#
|
|
# Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant :
|
|
#
|
|
# -1 0 1
|
|
# -2 0 2
|
|
# -1 0 1
|
|
#
|
|
def Sobel(self, drawer, pixelMap):
|
|
return self.Convolution(drawer, pixelMap, kernel=[
|
|
[-1, 0, 1],
|
|
[-2, 0, 2],
|
|
[-1, 0, 1]
|
|
] );
|
|
|
|
|
|
# Applique un filtre passe-haut à l'image de base vers l'image de sortie #
|
|
##########################################################################
|
|
# @param pixelMap Matrice de pixel à traiter (modifier)
|
|
#
|
|
#
|
|
# Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant :
|
|
#
|
|
# -1 0 1
|
|
# -2 0 2
|
|
# -1 0 1
|
|
#
|
|
def HighPass(self, drawer, pixelMap):
|
|
return self.Convolution(drawer, pixelMap, kernel=[
|
|
[ 0, -1, 0],
|
|
[-1, 5, -1],
|
|
[ 0, -1, 0]
|
|
] );
|
|
|
|
|
|
|
|
|
|
|
|
# applique le filtre de "convolution" sur l'image #
|
|
###################################################
|
|
# @param pixelMap la matrice de pixels à modifier
|
|
#
|
|
# @history
|
|
# applique le filtre
|
|
def Convolution(self, drawer, pixelMap, kernel=None):
|
|
width = len( pixelMap[0] )
|
|
height = len( pixelMap )
|
|
|
|
if kernel == None:
|
|
print "no kernel given!"
|
|
exit()
|
|
|
|
# nb total résultant du kernel des valeurs positives
|
|
kernelFactor = 0;
|
|
for b in kernel:
|
|
for a in b:
|
|
if a > 0:
|
|
kernelFactor += a;
|
|
|
|
kMidWidth = len( kernel[0] ) // 2
|
|
kMidHeight = len( kernel ) // 2
|
|
|
|
# map de résultat (filtrée)
|
|
convolvedMap = []
|
|
|
|
# on parcourt tout les pixels
|
|
for y in range(0, height):
|
|
|
|
# on rajoute une ligne à la map filtrée
|
|
convolvedMap.append( [] )
|
|
|
|
for x in range(0, width):
|
|
|
|
pixel = pixelMap[y][x];
|
|
|
|
# on définit la matrice de même taille que le kernel mais correspondant aux pixels superposés
|
|
pixelM = [];
|
|
|
|
for b in range(-kMidHeight, 1+kMidHeight):
|
|
pixelM.append( [] );
|
|
for a in range(-kMidWidth, 1+kMidWidth):
|
|
# on met les valeurs entre 0 et longueur ou largeur pour pas récupérer les valeurs de l'autre côté (lissage bizarre)
|
|
ruledX = 0 if x+a<0 else width-1 if x+a>=width else x+a;
|
|
ruledY = 0 if y+b<0 else height-1 if y+b>=height else y+b;
|
|
|
|
# if x+a<0 or x+a>=width or y+b<0 or y+b>=height: # si pixel dépasse de l'image, on l'ajoute pas
|
|
|
|
# on ajoute le pixel courant
|
|
pixelM[len(pixelM)-1].append( pixelMap[ruledY][ruledX] );
|
|
|
|
r,g,b = 0,0,0
|
|
|
|
# on effectue la convolution
|
|
for linePixelM, lineKernel in zip(pixelM, kernel):
|
|
for pix, fact in zip(linePixelM, lineKernel):
|
|
# pour chacun des filtres
|
|
r += pix.r * fact
|
|
g += pix.g * fact
|
|
b += pix.b * fact
|
|
|
|
r = int(r/kernelFactor) % 256
|
|
g = int(g/kernelFactor) % 256
|
|
b = int(b/kernelFactor) % 256
|
|
|
|
|
|
# définition des couleurs sur la map filtrée
|
|
convolvedMap[y].append( RGBPixel(
|
|
r = r,
|
|
g = g,
|
|
b = b,
|
|
x = x,
|
|
y = y,
|
|
bpp = pixel.bpp
|
|
) )
|
|
drawer.setPixel( convolvedMap[y][x] );
|
|
|
|
drawer.refresh();
|
|
|
|
return convolvedMap
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|