diff --git a/code/BMPFile.readme b/code/BMPFile.readme new file mode 100644 index 0000000..5b82a33 --- /dev/null +++ b/code/BMPFile.readme @@ -0,0 +1,224 @@ +Classes: + + BMPHeader + /***************/ + /* ATTRIBUTS */ + /***************/ + + * CONTENU BRUT PARTIEL (54 premiers bytes) + - header brut (binaire) + - header format liste de (0-255) + + * STRUCTURE DU HEADER + - signature (4D42) par défaut + - taille du fichier .bmp (bytes) + 4 bytes à 0 + - début du codage de l'image (bytes) + - taille du INFO_HEADER + - longueur de l'image (pixels) + - hauteur de l'image (pixels) + - nombre de plans (défaut: 1) + - nombre de bits par pixel (1,4,8,24) + - type de compression (0=none, 1=RLE-8, 2=RLE-4) + - taille de l'image avec padding (bytes) + - résolution horizontale (pixels) + - résolution verticale (pixels) + - nombre de couleurs de l'image (ou 0) + - nombre de couleurs importantes de l'image (ou 0) + + * VALEURS CALCULEES + - taille réelle d'une ligne +padding (bytes) + - taille du padding de fin de ligne (bytes) + + /***************/ + /* METHODES */ + /***************/ + parse(binHeader=""): + Définit les attributs à partir de ou de l'argument si défini + + unparse(): + Définit , et à partir de tout les attributs de structure + + + info(type=0): + Affiche les informations du header au format humain + peut valoir 0 (valeur par défaut) pour afficher en nombre, ou 1 pour afficher en hexa + + + toInt(bytes): + Retourne les octets sous forme d'entier + + fromInt(value, size): + Retourne une chaine de bytes correspondant au binaire de value + + + + + + BMPContent + /***************/ + /* ATTRIBUTS */ + /***************/ + + * CONTENU BRUT + - matrice de pixels brut (binaire) + - matrice de pixels format liste de (0-255) + + * CONTENU EXPLOITABLE + - matrice de pixels (instance of RGBPixel) + + + /***************/ + /* METHODES */ + /***************/ + parse(binContent="", header): + Définit les attributs à partir de ou de l'argument si défini ainsi que du header + + unparse(headerHandler=None): + Définit à partir map et définit aussi l'objet s'il est passé en paramètres + + + + + + BMPFile + /***************/ + /* ATTRIBUTS */ + /***************/ + * CONTENU PALETTE (fin du header jusqu'aux pixels) + - palette format binaire (header à offset) + - palette format list de (0-255) + + * CONTENU BRUT + - contenu complet brut (binaire) + - contenu complet format liste de (0-255) + + * CONTENU STRUCTURE + -
objet de type + - objet de type + + + /***************/ + /* METHODES */ + /***************/ + parse(binFile=""): + Définit les attributs à partir de ou de l'argument si défini + + unparse(): + Définit à partir des attributs et + + + + + + + + + RGBPixel + /***************/ + /* ATTRIBUTS */ + /***************/ + - byte rouge entre 0 et 255 + - byte vert entre 0 et 255 + - byte bleu entre 0 et 255 + + + /***************/ + /* METHODES */ + /***************/ + Constructeur(r, g, b): + Définit les attributs + + + + + + + + + + + + +############# +## To Do ## +############# +[x] gestion de la palette (attribut au ) définit par défaut au +[x] faire que le unparse du content créée le header +[ ] prise en charge des formats 1, 4, et 8 bpp + + + +####################################################################### +####### RECHERCHE DE PRISE EN CHARGE DES DIFFERENTS FORMATS BPP ####### +####################################################################### +PixelColor(r, g, b, bpp=24) + , , respectivement les composantes bleue, rouge, verte + correspond aux bpp + +CAS BPP=1 (noir et blanc) + (r+g+b)/3 >= 256 / 2 + + 1 - blanc + 2 - noir + +CAS BPP=4 (niveaux de gris) + 16 * ((r+g+b)/3) / 256 + +CAS BPP=8 + (r+g+b) / 3 + +class PixelColor(r, g, b, bpp=24): + if bpp not in [1,4,8,24]: + self.bpp = 24 + else: + self.bpp = bpp + + + self.r = r + self.g = g + self.b = b + + + # gestion des différents bpp + if bpp == 1: + self.intColor = int( (r+g+b)/3 > 256/2 ) + self.binColor = chr( self.intColor ) + elif bpp == 4: + self.intColor = int( 16 * ((r+g+b)/3) / 256 ) ) + self.binColor = chr( self.intColor ) + elif bpp == 8: + self.intColor = int( (r+g+b) / 3 ) + self.binColor = chr( self.intColor ) + else: + self.intColor = [r, g, b] + self.binColor = chr(b) + chr(g) + chr(r) + + + +####################################################################### +####### RECHERCHE DE PARSAGE DES PIXELS DE DIFFERENTS BPPS ####### +####################################################################### +ALGO: + + +firstBit = int(i) + i%1.0; # retourne le rang du premier bit (pas byte) +lastBit = firstBit + bpp/8.0 + +startByte = int( firstBit ) # ex: pour i =29, on a: 3 octets +startBit = int( 8 * (firstBit-startByte) ) # et 5 bits + +stopByte = int( lastBit ) +stopBit = int( 8 * (lastBit-stopByte) ) + +bytes = binData[startByte:stopByte+1] + +intArray = [ ord(x) for x in bytes ] +binArray = [ "0" + bin(x)[2:] for x in intArray ] +binArray = [ "0"*(8-len(binArray[x])) + binArray[x] for x in range(0, len(binArray)) ] +binary = "" +for byte in binArray: + binary += byte; + +print binArray +print "%s to %s => %s" % ( startBit, 8*(stopByte-startByte)+stopBit, binary[startBit:8*(stopByte-startByte) + stopBit] ) \ No newline at end of file diff --git a/code/Noise.readme b/code/Noise.readme new file mode 100644 index 0000000..dcd47f2 --- /dev/null +++ b/code/Noise.readme @@ -0,0 +1,69 @@ +Classes: + + +/******************/ +/** COLORIZATION **/ +/******************/ +Principe: colorer en modifiant les pixels (n&b) dans un ton (teinte) précisée + +restitue la contraste mais recentre la couleur autour de la teinte +/************ ALGO **************/ +i = 50 // incertitude +t = RGBPixel(1,2,3) // teinte souhaitée +p = RGBPixel(1,2,3) // couleur actuelle + +/************ CODE **************/ +def colorize(pixel, tint): + + + + +/*****************/ +/** SHAPIZATION **/ +/*****************/ +Principe: récupérer une forme par récurrence + +Ajouter les 8 bits périphériques du pixel courant s'il existe et s'il a des couleurs pas trop éloignées des précédentes +/************ ALGO **************/ + +/************ CODE **************/ +def getShape(self, coords, pixelMap, pixelList ): # return PixelList + # coords = [lastx, lasty, x, y] + width = len( pixelMap[0] ) + height = len( pixelMap ) + + lastx = coords[0] + lasty = coords[1] + x = coords[2] + y = coords[3] + + newCoords = [x, y] + + + # si le pixel existe (pas de dépassement de la pixelMap) + if x=0 and y=0: + + already = False; + for i in range(0, len(pixelList)): + if pixelList[i] == pixelMap[y][x]: + already = True; + break + + # si le pixel n'est pas déjà dans le tableau + if not already: + + pixelMap[y][x].setRGB(255,0,0); # debug, tout rouge + + pixelList.append( pixelMap[y][x] ) # ajout au tableau + + self.getShape(newCoords+[x-1, y+1], pixelMap, pixelList) # 1 + self.getShape(newCoords+[x, y+1], pixelMap, pixelList) # 2 + self.getShape(newCoords+[x+1, y+1], pixelMap, pixelList) # 3 + + self.getShape(newCoords+[x-1, y], pixelMap, pixelList) # 4 + # current pixel + self.getShape(newCoords+[x+1, y], pixelMap, pixelList) # 6 + + self.getShape(newCoords+[x-1, y-1], pixelMap, pixelList) # 7 + self.getShape(newCoords+[x, y-1], pixelMap, pixelList) # 8 + self.getShape(newCoords+[x+1, y-1], pixelMap, pixelList) # 9 \ No newline at end of file diff --git a/code/bmp.py b/code/bmp.py new file mode 100644 index 0000000..c8da8a6 --- /dev/null +++ b/code/bmp.py @@ -0,0 +1,65 @@ +# ~*~ encoding: utf-8 ~*~ # +########################### +# TRAITEMENT D'IMAGES # +########################### + +# classes +from BMPFile import * +from Noise import * +import random +import sys + + + + + + + + + + + +def testFileIntegrity(): + # lecture du fichier + with open( sys.argv[1] ) as file: + binFile = file.read() + + # Instanciation du BMPFile + img = BMPFile() + # Instanciation du NoiseObject + noise = Noise(); + + # Parsing + img.parse( binFile ); + + noise.SaltAndPepper_set(10, img.content.map) + + + # Unparsing + img.unparse(newBpp=24) + + print img.binData + + + + + +def testManualCreation(): + img = BMPFile() + for y in range(0, 100): + img.content.map.append( [] ) + for x in range(0, 100): + img.content.map[y].append( RGBPixel( + random.randint(0, 255), + random.randint(0, 255), + random.randint(0, 255), + bpp=24 + ) ); + + img.unparse(); + + print img.binData + +# MAIN +#testManualCreation() +testFileIntegrity() \ No newline at end of file diff --git a/code/created/noir_blanc_8.bmp b/code/created/noir_blanc_8.bmp new file mode 100644 index 0000000..4831d6e Binary files /dev/null and b/code/created/noir_blanc_8.bmp differ diff --git a/code/created/vert_rose_24.bmp b/code/created/vert_rose_24.bmp new file mode 100644 index 0000000..9c5ef02 Binary files /dev/null and b/code/created/vert_rose_24.bmp differ diff --git a/code/main.py b/code/main.py index 7ed1c7a..7db8125 100644 --- a/code/main.py +++ b/code/main.py @@ -68,6 +68,7 @@ print "| 43) %s |" % exactLength("Prewitt", 21, -1) print "| 44) %s |" % exactLength("Sobel", 21, -1) print "| 45) %s |" % exactLength("Convolution", 21, -1) print "| 46) %s |" % exactLength("bichrome", 21, -1) +print "| 47) %s |" % exactLength("Passe Haut", 21, -1) print "+---------------------------+" print while True: @@ -207,6 +208,9 @@ elif action == 45: elif action == 46: print startStr testBichrome() # teste le passage au bichromatique +elif action == 47: + print startStr + testHighPass() # teste le filtre passe haut else: print "Wrong choice" diff --git a/code/new.bmp b/code/new.bmp new file mode 100644 index 0000000..a8d5b1e Binary files /dev/null and b/code/new.bmp differ diff --git a/code/tests.py b/code/tests.py index 8f11ee6..6d530de 100644 --- a/code/tests.py +++ b/code/tests.py @@ -1453,3 +1453,48 @@ def testBichrome(): +# teste le filtre de passe haut sur d'une image # +################################################# +# @sysarg 1 le fichier d'origine +# @stsarg 2 le fichier de sortie (filtré) +# +# @history +# Parse le fichier d'origine +# Applique le filtre +# Unparse l'image et l'enregistre dans le fichier de sortie +def testHighPass(): + t = Timer(); + + + # lecture du fichier + print "| Reading Image |",; t.reset(); + with open( sys.argv[1] ) as file: + binFile = file.read() + print "%s |" % (t.get()) + + + img = BMPFile(); # Instanciation du BMPFile + + + # Parsing + print "| Parsing file |",; t.reset(); + img.parse( binFile ); + print "%s |" % (t.get()) + + + print "| Application du filtre |",; t.reset(); + img.content.map = FX.Filter.HighPass(img.content.map); + print "%s |" % (t.get()) + + # Unparsing + print "| Unparsing file |",; t.reset(); + img.unparse() + print "%s |" % (t.get()) + + # image to stdout + print "| Writing file |",; t.reset(); + img.write( sys.argv[2] ) + print "%s |" % (t.get()) + + + diff --git a/code/utility/Filter.py b/code/utility/Filter.py index 28fefab..bccbf5f 100644 --- a/code/utility/Filter.py +++ b/code/utility/Filter.py @@ -19,13 +19,13 @@ class Filter: # Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant : # # 1 1 1 - # 1 0 1 + # 1 1 1 # 1 1 1 # def averageFilter(self, pixelMap): return self.Convolution(pixelMap, kernel=[ [1, 1, 1], - [1, 0, 1], + [1, 1, 1], [1, 1, 1] ] ); @@ -84,6 +84,25 @@ class Filter: ] ); + # 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, pixelMap): + return self.Convolution(pixelMap, kernel=[ + [ 0, -1, 0], + [-1, 5, -1], + [ 0, -1, 0] + ] ); + + diff --git a/dossier/Vectorization/shape.jpg b/dossier/Vectorization/shape.jpg new file mode 100644 index 0000000..96bca88 Binary files /dev/null and b/dossier/Vectorization/shape.jpg differ diff --git a/dossier/Vectorization/shapeDetection1.jpg b/dossier/Vectorization/shapeDetection1.jpg new file mode 100644 index 0000000..2796de3 Binary files /dev/null and b/dossier/Vectorization/shapeDetection1.jpg differ diff --git a/dossier/Vectorization/shapeDetection2.jpg b/dossier/Vectorization/shapeDetection2.jpg new file mode 100644 index 0000000..f15da40 Binary files /dev/null and b/dossier/Vectorization/shapeDetection2.jpg differ diff --git a/dossier/Vectorization/shapeDetection3.jpg b/dossier/Vectorization/shapeDetection3.jpg new file mode 100644 index 0000000..77e88c7 Binary files /dev/null and b/dossier/Vectorization/shapeDetection3.jpg differ diff --git a/dossier/dossier.pdf b/dossier/dossier.pdf index d38bb26..cac8f49 100644 Binary files a/dossier/dossier.pdf and b/dossier/dossier.pdf differ diff --git a/dossier/dossier.tex b/dossier/dossier.tex index 6231c26..13da2d0 100644 --- a/dossier/dossier.tex +++ b/dossier/dossier.tex @@ -548,15 +548,32 @@ On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur\\ \indent \emph{Méthode 2 - indépendentisation de contour}\\ - L'image est lissée avec un filtre moyen. Nous effectuons un produit de convolution (noté \begin{math}\otimes\end{math}) avec l'image \emph{I} et le noyau tel que défini : - \begin{align*} - I_{lisse} = I\ \otimes\ \frac{1}{8} \begin{pmatrix} - 1 & 1 & 1\\ - 1 & 0 & 1\\ - 1 & 1 & 1 - \end{pmatrix} - \end{align*} - On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur + Un algorithme lance sur chaque pixel de l'image un "envahisseur", c'est-à-dire un algorithme qui référencie chaque pixel considéré dans la même forme que le pixel de départ. par exemple, on obtient le résultat ci-dessous en essayant de récupérer les formes noires uniquement : + % indépendentisation de contour + \begin{figure}[!ht] + \centering + \begin{minipage}[t]{3.5cm} + \centering + \includegraphics[width=3.5cm]{Vectorization/shape.jpg} + Image originale + \end{minipage} + \begin{minipage}[t]{3.5cm} + \centering + \includegraphics[width=3.5cm]{Vectorization/shapeDetection1.jpg} + Détection sur forme 1 + \end{minipage} + \begin{minipage}[t]{3.5cm} + \centering + \includegraphics[width=3.5cm]{Vectorization/shapeDetection2.jpg} + Détection sur forme 2 + \end{minipage} + \begin{minipage}[t]{3.5cm} + \centering + \includegraphics[width=3.5cm]{Vectorization/shapeDetection3.jpg} + Détection sur forme 3 + \end{minipage} + \end{figure}\\ + Les résultats sont corrects mais le traitement devient vite très long, le temps d'éxécution moyen pour ces résultats est de 20 secondes. Nous avons donc décidé de créer un nouvel algorithme qui lui récupérerait uniquement les contours. \newpage