This commit is contained in:
xdrm-brackets 2015-11-13 12:41:22 +01:00
parent aa23e11378
commit de1f6c2130
46 changed files with 375 additions and 857 deletions

197
code/Convolution_Test.py Normal file
View File

@ -0,0 +1,197 @@
# ~*~ Encoding: utf-8 ~*~ #
class RGBPixel:
def __init__(self, r, g, b, x, y):
self.r = r;
self.g = g;
self.b = b;
self.x = x;
self.y = y;
def setRGBPixel(self, r, g, b, x, y):
self.__init__(r, g, b, x, y);
def setRGB(self, r, g, b):
self.r = r;
self.g = g;
self.b = b;
def setXY(self, x, y):
self.x = x;
self.y = y;
def toString(self):
return 'rgb(%s, %s, %s)' % (self.r, self.g, self.b);
def toString_grayscale(self):
return (self.r+self.g+self.b) // 3;
def printRGBMatrix(m):
for line in m:
print '|',
for row in line:
print '%s |' % ( row.toString_grayscale() ),
print;
def printMatrix(m):
for line in m:
print '|',
for row in line:
print '%s |' % ( row ),
print;
# applique le filtre de "convolution" sur l'image #
###################################################
# @param pixelMap la matrice de pixels à modifier
#
# @history
# applique le filtre
def Convolution(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
print '(%s) * %s' % ( pix.r, fact );
print;
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
) )
return convolvedMap
# on définit une matrice de base
pixelSample = [ RGBPixel(50, 50, 50, 0, 0),
RGBPixel(100, 100, 100, 0, 0) ];
# on définit la matrice 10x5
matrix50 = [];
for y in range(0,3):
matrix50.append( [] );
for x in range(0,3):
pixelSample[(x+y*3)%2].setXY(x, y);
matrix50[y].append( pixelSample[(x+y*5)%2] );
# on l'affiche
printRGBMatrix(matrix50);print;
# on définit le noyau 3x3
k = [ [1, 1, 1],
[1, 0, 1],
[1, 1, 1] ];
# on l'affiche
printMatrix(k);print;
matrix50Convolved = Convolution(matrix50, k);
printRGBMatrix(matrix50Convolved);print;
printRGBMatrix(matrix50);print;

BIN
code/blur.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

BIN
code/contours.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 KiB

BIN
code/dossier/stroke.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

View File

@ -1,28 +0,0 @@
import pygtk
pygtk.require('2.0')
import gtk
def select_file():
dialog = gtk.FileChooserDialog("Open ...",
None,
gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
dialog.set_default_response(gtk.RESPONSE_OK)
filter = gtk.FileFilter()
filter.set_name("All files");
filter.add_pattern("*")
dialog.add_filter(filter)
response = dialog.run()
if response == gtk.RESPONSE_OK:
print dialog.get_filename(), 'selected'
select = dialog.get_filename()
elif response == gtk.RESPONSE_CANCEL0:
print 'Cosed, no files selected'
select = "error"
dialog.destroy()
print "Nom du fichier selectionne :" + select
return select

View File

@ -1,113 +0,0 @@
import pygtk
pygtk.require('2.0')
import gtk
from interface.Explorateur import *
class Interface:
#DEFINITION DES EVENEMENT BOUTON
def evnmt_quitter(self, widget, donnees = None):
print "Evnmt delete survenu"
gtk.main_quit()
def evnmt_exploreur(self, widget, donnees = None):
print "Evnmt explorateur survenu"
self.name = select_file() #stoque le nom du fichier selection dans cette variable
self.libelle.set_label("fichier selectionne : " + self.name)
def evnmt_refresh_text(self, widget, donnees = None):
print "Evenement refresh"
print self.bouton3.get_label()
print self.diag.get_text()
self.bouton3.set_label(self.diag.get_text())
#EVENEMENT COMBOBOX
def changed_cb(self, widget):
print "coucou toi"
str1 = self.get_active_text(widget)
self.traitement_img(str1)
def get_active_text(self, widget):
modele = widget.get_model()
est_actif = widget.get_active()
if est_actif < 0:
return None
return modele[est_actif][0]
#fonction qui repere l option choisit
def traitement_img(self, str1):
if str1 == "Additif(Gaussien)":
print "gaussien"
elif str1 == "Additif(Bernouilli)":
print "bernouilli"
elif str1 == "Salt and Pepper":
print "salt and peper"
else:
print "Not found"
def __init__(self):
self.fen = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.fen.set_title("Traitement d image")
self.fen.set_default_size(500, 500)
self.fen.connect("delete_event", self.evnmt_quitter)
#creation du libelle
self.libelle = gtk.Label("Aucun fichier selectionnee")
#creation de la zone de dialogue
#self.diag = gtk.Entry(0)
self.diag = gtk.Entry(0)
self.diag.set_text("nom du fichier qui contiendra la nouvelle image")
#Creationd une combo box
self.combo = gtk.combo_box_new_text()
self.combo.append_text("Salt and Pepper")
self.combo.append_text("Additif(Bernouilli)")
self.combo.append_text("Additif(Gaussien)")
self.combo.connect('changed', self.changed_cb)
#creation des boutons
self.bouton = gtk.Button("Explorateur de fichier")
self.bouton2 = gtk.Button("Quitter le programme")
self.bouton3 = gtk.Button("Texte entree")
self.bouton.connect("clicked", self.evnmt_exploreur)
self.bouton2.connect("clicked", self.evnmt_quitter)
self.bouton3.connect("clicked", self.evnmt_refresh_text)
self.box = gtk.VBox(False, 0)
self.box1 = gtk.HBox(False, 0)
self.box2 = gtk.HBox(False, 0)
self.fen.add(self.box)
#Gestion des differents elements de la fenetre
#box 1 permet de creer deux elements sur la meme igne de box
self.box1.pack_start(self.bouton, True, True, 0) #bouton d explorateur
self.box1.pack_start(self.bouton2, True, True, 0)#bouton pour quitter le porogramme
self.box.pack_start(self.box1, True, True, 0) #ajout d une boite dans une boite
self.box.pack_start(self.libelle, True, True, 0) #ajout du libelle contenant le chemin ou non du fichier selectionnne
self.box.pack_start(self.box2, True, True, 0)
self.box2.pack_start(self.diag, True, True, 0)
self.box.pack_start(self.bouton3)
self.box.pack_start(self.combo)
self.bouton.show()
self.bouton2.show()
self.bouton3.show()
self.libelle.show()
self.diag.show()
self.combo.show()
self.box.show()
self.box1.show()
self.box2.show()
self.fen.show()
def boucle(self):
gtk.main()
if __name__ == "__main__":
m = Test()
m.boucle()

View File

@ -231,7 +231,8 @@ def interfaceLoop():
print '- [PRESS ANY KEY TO CONTINUE] -'; print '- [PRESS ANY KEY TO CONTINUE] -';
print '- [ BUT PRESS "Q" TO QUIT ] -'; print '- [ BUT PRESS "Q" TO QUIT ] -';
print '- [ OR PRESS "R" TO RELOAD ] -'; print '- [ OR PRESS "R" TO RELOAD ] -';
loopKey = raw_input('- [ OR PRESS "S" TO SAVE ] -'); print '- [ OR PRESS "S" TO SAVE ] -';
loopKey = raw_input(': ');
if( loopKey == 'q' or loopKey == 'Q' ): if( loopKey == 'q' or loopKey == 'Q' ):
exit(); exit();

View File

@ -1,399 +0,0 @@
# ~*~ encoding: utf-8 ~*~ #
###########################
# TRAITEMENT D'IMAGES #
###########################
# classes
from BMPFile import *
from Noise import *
from tests import *
import random
import sys
from os import system as sh
import time
# test par défaut puis quitte
# defaultTest();
# exit();
# arrêt si moins de 2 arguments
if len(sys.argv) < 3:
print "Require 2 args : \n* input image\n* output image"
exit()
import pygtk
pygtk.require('2.0')
import gtk
from interface.Explorateur import *
class Interface:
#DEFINITION DES EVENEMENT BOUTON
def evnmt_quitter(self, widget, donnees = None):
print "Evnmt delete survenu"
gtk.main_quit()
def evnmt_exploreur(self, widget, donnees = None):
self.name = select_file() #stoque le nom du fichier selection dans cette variable
self.libelle.set_label("fichier selectionne : " + self.name)
def evnmt_refresh_text(self, widget, donnees = None):
print "Evenement refresh"
print self.bouton3.get_label()
print self.diag.get_text()
self.bouton3.set_label(self.diag.get_text())
#EVENEMENT COMBOBOX
def changed_cb(self, widget):
print "coucou toi"
str1 = self.get_active_text(widget)
self.traitement_img(str1)
def get_active_text(self, widget):
modele = widget.get_model()
est_actif = widget.get_active()
if est_actif < 0:
return None
return modele[est_actif][0]
#fonction qui repere l option choisit
def traitement_img(self, str1):
interfaceSelection(self.combo.get_active())
def __init__(self):
self.fen = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.fen.set_title("Traitement d image")
self.fen.set_default_size(500, 500)
self.fen.connect("delete_event", self.evnmt_quitter)
#creation du libelle
self.libelle = gtk.Label("Aucun fichier selectionnee")
#creation de la zone de dialogue
#self.diag = gtk.Entry(0)
self.diag = gtk.Entry(0)
self.diag.set_text("nom du fichier qui contiendra la nouvelle image")
#Creationd une combo box
self.combo = gtk.combo_box_new_text()
self.combo.set_wrap_width(4);self.combo.set_entry_text_column(1)
self.combo.set_column_span_column(10);
self.combo.append_text( "Traitement à effectuer:" );
self.combo.append_text( "*** TESTS DE FICHIER ***" );
self.combo.append_text( "Creation manuelle" );
self.combo.append_text( "Parse/Unparse" );
self.combo.append_text( "Afficher palette" );
self.combo.append_text( "" );
self.combo.append_text( "*** TESTS DE BRUIT ***" );
self.combo.append_text( "Salt&Pepper" );
self.combo.append_text( "Additif (Bernouilli)" );
self.combo.append_text( "Additif (Gaussien)" );
self.combo.append_text( "" );
self.combo.append_text( "*** TESTS DE DIFFERENCES ***" );
self.combo.append_text( "Difference en %" );
self.combo.append_text( "SNR (origine/bruit)" );
self.combo.append_text( "Difference en image" );
self.combo.append_text( "Fusion d'images (+)" );
self.combo.append_text( "Fusion d'images (-)" );
self.combo.append_text( "" );
self.combo.append_text( "*** TESTS DE FORMES ***" );
self.combo.append_text( "Reveler une teinte" );
self.combo.append_text( "Colorer une forme" );
self.combo.append_text( "Colorer les formes" );
self.combo.append_text( "Relever les contours" );
self.combo.append_text( "" );
self.combo.append_text( "*** TESTS DE FILTRES ***" );
self.combo.append_text( "Filtre moyen" );
self.combo.append_text( "Laplace" );
self.combo.append_text( "Roberts" );
self.combo.append_text( "Prewitt" );
self.combo.append_text( "Sobel" );
self.combo.append_text( "Convolution" );
self.combo.append_text( "bichrome" );
self.combo.append_text( "Passe Haut" );
self.combo.connect('changed', self.changed_cb)
self.combo.set_active(0);
#creation des boutons
self.bouton = gtk.Button("Explorateur de fichier")
self.bouton2 = gtk.Button("Quitter le programme")
self.bouton3 = gtk.Button("Texte entree")
self.bouton.connect("clicked", self.evnmt_exploreur)
self.bouton2.connect("clicked", self.evnmt_quitter)
self.bouton3.connect("clicked", self.evnmt_refresh_text)
self.box = gtk.VBox(False, 0)
self.box1 = gtk.HBox(False, 0)
self.box2 = gtk.HBox(False, 0)
self.fen.add(self.box)
#Gestion des differents elements de la fenetre
#box 1 permet de creer deux elements sur la meme igne de box
self.box1.pack_start(self.bouton, True, True, 0) #bouton d explorateur
self.box1.pack_start(self.bouton2, True, True, 0)#bouton pour quitter le porogramme
self.box.pack_start(self.box1, True, True, 0) #ajout d une boite dans une boite
self.box.pack_start(self.libelle, True, True, 0) #ajout du libelle contenant le chemin ou non du fichier selectionnne
self.box.pack_start(self.box2, True, True, 0)
self.box2.pack_start(self.diag, True, True, 0)
self.box.pack_start(self.bouton3)
self.box.pack_start(self.combo)
self.bouton.show()
self.bouton2.show()
self.bouton3.show()
self.libelle.show()
self.diag.show()
self.combo.show()
self.box.show()
self.box1.show()
self.box2.show()
self.fen.show()
def boucle(self):
gtk.main()
m = Interface()
################" INTERFACE "###################
def interfaceSelection(action):
startStr = "\n+---------------------------+---------+"
result = ""
execTime = Timer(); execTime.reset();
# fichier
if action == 2:
w = raw_input("width [100]: ")
h = raw_input("height [100]: ")
arg1, arg2 = 100, 100
if w != "":
arg1 = int(w)
if h != "":
arg2 = int(h)
print startStr
testManualCreation(image1, arg1, arg2) # teste la création d'un fichier à partir d'une matrice uniquement
elif action == 3:
print startStr
result = testFileIntegrity(image1) # teste le PARSE/UNPARSE
elif action == 4:
print startStr
result = printIntPalette(image1) # affiche la palette d'une image
# bruits
elif action == 7:
inS = raw_input("seuil bruitage [50]: ")
outS = raw_input("seuil débruitage [1] : ")
outB = raw_input("borne débruitage [1] : ")
s = raw_input("Lissage ? (0-1): ")
arg1, arg2, arg3, arg4 = 50, 1, 1, 1
if inS != "":
arg1 = int(inS)
if outS != "":
arg2 = int(outS)
if outB != "":
arg3 = int(outB)
if s != "":
arg4 = int(s)
print startStr
testSaltAndPepper(image1, arg1, arg2, arg3, arg4) # teste le bruitage/débruitage de type "Sel & Poivre"
elif action == 8:
inS = raw_input("seuil bruitage [10]: ")
outS = raw_input("seuil débruitage [35] : ")
arg1, arg2 = 10, 35
if inS != "":
arg1 = int(inS)
if outS != "":
arg2 = int(outS)
print startStr
testAdditiveBernouilliNoise(image1, arg1, arg2) # teste le bruitage/débruitage de type "Additif"
elif action == 9:
inS = raw_input("sigma [10]: ")
outS = raw_input("seuil débruitage [35] : ")
arg1, arg2 = 10, 35
if inS != "":
arg1 = int(inS)
if outS != "":
arg2 = int(outS)
print startStr
testAdditiveGaussianNoise(image1, arg1, arg2) # teste le bruitage/débruitage de type "Additif"
# performances
elif action == 12:
print startStr
printImageQuality(image1, image2) # compare 2 images et donne le pourcentage de ressemblance/différence
elif action == 13:
print startStr
printSNR(image1, image2) # compare 2 images et retourne le SNR
elif action == 14:
print startStr
imageForImageQuality(image1, image2) # crée une image correspondant aux différences de 2 images
elif action == 15:
print startStr
mergeImagesAdditive(image1, image2) # crée une image étant la fusion (addition) de 2 images
elif action == 16:
print startStr
mergeImagesSubstractive(image1, image2) # crée une image étant la fusion (soustractive) de 2 images
elif action == 19:
r = raw_input("rouge [0]: ")
g = raw_input("vert [0]: ")
b = raw_input("bleu [0]: ")
s = raw_input("seuil [50]: ")
arg1, arg2, arg3, arg4 = 0,0,0,50
if r != "":
arg1 = int(r)
if g != "":
arg2 = int(g)
if b != "":
arg3 = int(b)
if s != "":
arg4 = int(s)
print startStr
revealShapes(image1, arg1, arg2, arg3, arg4) # révèle la couleur spécifiée
elif action == 20:
x = raw_input("abscisses(x) [0]: ")
y = raw_input("ordonnées(y) [0]: ")
arg1, arg2 = 0,0
if x != "":
arg1 = int(x)
if y != "":
arg2 = int(y)
print startStr
colorShape(image1, arg1, arg2) # colorie la forme contenant le pixel de coordonnées donné
elif action == 21:
print startStr
colorAllShapes(image1) # colorie la forme contenant le pixel de coordonnées donné
elif action == 22:
print startStr
testStroke(image1) # trace les contours uniquement à partir de formes pleines
# filtres
elif action == 25:
print startStr
testAverageFilter(image1) # teste le lissage
elif action == 26:
print startStr
testLaplace(image1) # teste le filtre de Laplace
elif action == 27:
print startStr
testRoberts(image1) # teste le filtre de Roberts
elif action == 28:
print startStr
testPrewitt(image1) # teste le filtre de Prewitt
elif action == 29:
print startStr
testSobel(image1) # teste le filtre de Sobel
elif action == 30:
print startStr
testConvolution(image1) # teste le filtre de Convolution
elif action == 31:
print startStr
testBichrome(image1) # teste le passage au bichromatique
elif action == 32:
print startStr
testHighPass(image1) # teste le filtre passe haut
else:
print "Wrong choice"
exit();
print "+---------------------------+---------+"
print "| EXECUTION TIME | %s |" % execTime.get()
print "+---------------------------+---------+"
print
print result
print '- [PRESS ANY KEY TO CONTINUE] -';
print '- [ BUT PRESS "Q" TO QUIT ] -';
print '- [ OR PRESS "R" TO RELOAD ] -';
loopKey = raw_input('- [ OR PRESS "S" TO SAVE ] -');
if( loopKey == 'q' or loopKey == 'Q' ):
exit();
elif( loopKey == 'r' or loopKey == 'R' ):
loadFiles();
elif( loopKey == 's' or loopKey == 'S' ):
out = raw_input("out file: ");
image1.unparse();
image1.write(out);
interfaceLoop();
################" EXECUTABLE "###################
sh('clear');
print "+---------------------------+"
print "| |"
print "| CHARGEMENT... |"
print "| |"
print "+---------------------------+"
# ON CREE LES IMAGES
image1, file1 = BMPFile(True), "";
image2, file2 = BMPFile(), "";
with open( sys.argv[1] ) as file:
file1 += file.read();
try:
with open( sys.argv[2] ) as file:
file2 += file.read()
except Exception as e:
print e;
def loadFiles():
image1.parse( file1 );
for line in image1.content.map:
for pix in line:
image1.drawer.setPixel( pix );
image1.drawer.refresh();
if( file2 != "" ):
image2.parse( file2 );
loadFiles();
m.boucle()
# interfaceLoop();

BIN
code/noiruniquement.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
code/stroke.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

View File

@ -1,22 +0,0 @@
+-------+
| To Do |
+-------+
Centraliser les fonctions:
Ne plus séparer par type de fonctions (ex: bruit A, bruit B, bruit C, ...)
Mais plutôt factoriser
+-------+
| Doing |
+-------+
+------+
| Done |
+------+

View File

@ -1,224 +0,0 @@
Classes:
BMPHeader
/***************/
/* ATTRIBUTS */
/***************/
* CONTENU BRUT PARTIEL (54 premiers bytes)
- <binData> header brut (binaire)
- <intData> header format liste de (0-255)
* STRUCTURE DU HEADER
- <signature> signature (4D42) par défaut
- <fileSize> taille du fichier .bmp (bytes)
4 bytes à 0
- <offset> début du codage de l'image (bytes)
- <infoSize> taille du INFO_HEADER
- <width> longueur de l'image (pixels)
- <height> hauteur de l'image (pixels)
- <plans> nombre de plans (défaut: 1)
- <bpp> nombre de bits par pixel (1,4,8,24)
- <compType> type de compression (0=none, 1=RLE-8, 2=RLE-4)
- <size> taille de l'image avec padding (bytes)
- <horiRes> résolution horizontale (pixels)
- <vertRes> résolution verticale (pixels)
- <colorNb> nombre de couleurs de l'image (ou 0)
- <colorINb> nombre de couleurs importantes de l'image (ou 0)
* VALEURS CALCULEES
- <rowSize> taille réelle d'une ligne +padding (bytes)
- <padding> taille du padding de fin de ligne (bytes)
/***************/
/* METHODES */
/***************/
parse(binHeader=""):
Définit les attributs à partir de <binData> ou de l'argument <binHeader> si défini
unparse():
Définit <binData>, et <intData> à partir de tout les attributs de structure
info(type=0):
Affiche les informations du header au format humain
<type> peut valoir 0 (valeur par défaut) pour afficher en nombre, ou 1 pour afficher en hexa
toInt(bytes):
Retourne les octets <bytes> sous forme d'entier
fromInt(value, size):
Retourne une chaine de <size> bytes correspondant au binaire de value
BMPContent
/***************/
/* ATTRIBUTS */
/***************/
* CONTENU BRUT
- <binData> matrice de pixels brut (binaire)
- <intData> matrice de pixels format liste de (0-255)
* CONTENU EXPLOITABLE
- <map> matrice de pixels (instance of RGBPixel)
/***************/
/* METHODES */
/***************/
parse(binContent="", header):
Définit les attributs à partir de <binData> ou de l'argument <binContent> si défini ainsi que du header
unparse(headerHandler=None):
Définit <bin> à partir map et définit aussi l'objet <headerHandler> s'il est passé en paramètres
BMPFile
/***************/
/* ATTRIBUTS */
/***************/
* CONTENU PALETTE (fin du header jusqu'aux pixels)
- <binPalette> palette format binaire (header à offset)
- <intPalette> palette format list de (0-255)
* CONTENU BRUT
- <binData> contenu complet brut (binaire)
- <intData> contenu complet format liste de (0-255)
* CONTENU STRUCTURE
- <header> objet de type <BMPHeader>
- <content> objet de type <BMPContent>
/***************/
/* METHODES */
/***************/
parse(binFile=""):
Définit les attributs à partir de <binData> ou de l'argument <binFile> si défini
unparse():
Définit <binData> à partir des attributs <BMPHeader> et <BMPContent>
RGBPixel
/***************/
/* ATTRIBUTS */
/***************/
- <r> byte rouge entre 0 et 255
- <g> byte vert entre 0 et 255
- <b> byte bleu entre 0 et 255
/***************/
/* METHODES */
/***************/
Constructeur(r, g, b):
Définit les attributs
#############
## To Do ##
#############
[x] gestion de la palette (attribut au <parse>) définit par défaut au <unparse>
[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)
<r>, <g>, <b> respectivement les composantes bleue, rouge, verte
<bpp> 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] )

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -73,7 +73,11 @@
\begin{figure}[!ht] \begin{figure}[!ht]
\centering \centering
\includegraphics{fileTree.jpg} \begin{minipage}[t]{8cm}
\centering
\includegraphics{st3/File_Architecture.jpg}
Figure 1. Structure de fichiers
\end{minipage}
\end{figure} \end{figure}
\begin{description} \begin{description}
@ -121,6 +125,14 @@
Soit le couple \begin{math}(x,y)\in\N^2\end{math}, les coordonnés d'un pixel dans I, tel que \begin{math}x\in[0;n_x[,\ et\ y\in[0;n_y[\end{math}.\\ Soit le couple \begin{math}(x,y)\in\N^2\end{math}, les coordonnés d'un pixel dans I, tel que \begin{math}x\in[0;n_x[,\ et\ y\in[0;n_y[\end{math}.\\
Soit \begin{math}\vec{u}\end{math} le vecteur associé à une unité de contour, tel que \begin{math}||\vec{u}|| = 1,\ et\ sa\ direction\ d =\frac{n\pi}{2}[2\pi]\ rad,\ avec\ n\in\N\end{math}.\\ Soit \begin{math}\vec{u}\end{math} le vecteur associé à une unité de contour, tel que \begin{math}||\vec{u}|| = 1,\ et\ sa\ direction\ d =\frac{n\pi}{2}[2\pi]\ rad,\ avec\ n\in\N\end{math}.\\
Soit \begin{math}K_n\end{math}, la matrice carré d'ordre \emph{n}. Par exemple \begin{math}K_3 = \begin{pmatrix}k_1&k_2&k_3\\k_4&k_5&k_6\\k_7&k_8&k_9\\\end{pmatrix}\end{math}\\\\ Soit \begin{math}K_n\end{math}, la matrice carré d'ordre \emph{n}. Par exemple \begin{math}K_3 = \begin{pmatrix}k_1&k_2&k_3\\k_4&k_5&k_6\\k_7&k_8&k_9\\\end{pmatrix}\end{math}\\\\
Afin de comparer les images nous avons implémenté le SNR, qui permet de donner calculer la qualité du débruitage.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/import_UTILITY.jpg}\\
Figure 2. Implémentation du SNR.
\end{center}
\end{figure}
\newpage \newpage
@ -233,6 +245,13 @@
Le \emph{bitmap} du fichier (matrice de pixels) peut avoir plusieurs formats qui sont propres au nombre de bits par pixels et dépendent de la \emph{palette}. De plus la matrice est dans l'ordre inverse, c'est à dire que le premier pixel est en fait le dernier, il convient donc d'inverser les lignes et les colonnes. De manière générale les pixels sont enregistrés en une succession de lignes. Le nombre d'octets de chaque ligne doit être un multiple de 4, est donc ajouté en fin de ligne un <<padding>> composé de 0 à 3 octets ayant pour valeur zéro. Le \emph{bitmap} du fichier (matrice de pixels) peut avoir plusieurs formats qui sont propres au nombre de bits par pixels et dépendent de la \emph{palette}. De plus la matrice est dans l'ordre inverse, c'est à dire que le premier pixel est en fait le dernier, il convient donc d'inverser les lignes et les colonnes. De manière générale les pixels sont enregistrés en une succession de lignes. Le nombre d'octets de chaque ligne doit être un multiple de 4, est donc ajouté en fin de ligne un <<padding>> composé de 0 à 3 octets ayant pour valeur zéro.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/BMPFile.jpg}
Figure 3. Structure du fichier BMPFile.py
\end{center}
\end{figure}
@ -309,6 +328,17 @@
\end{figure} \end{figure}
On remarque bien ici que les contours subissent un <<effet escalier>> ce qui dégrade en majeure partie le rendu. Nous avons réglé partiellement ce problème en ajoutant un lissage au processus de débruitage, mais le lissage réduit aussi la netteté de l'image. Par contre, les couleurs sont convenablement restituées, de même pour les teintes et contrastes. Il suffirait de traiter l'image en prenant en compte les contours, ce qui permettrait de gagner en qualité. On remarque bien ici que les contours subissent un <<effet escalier>> ce qui dégrade en majeure partie le rendu. Nous avons réglé partiellement ce problème en ajoutant un lissage au processus de débruitage, mais le lissage réduit aussi la netteté de l'image. Par contre, les couleurs sont convenablement restituées, de même pour les teintes et contrastes. Il suffirait de traiter l'image en prenant en compte les contours, ce qui permettrait de gagner en qualité.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/Salt&Pepper_SET.jpg}\\
Figure 4. Création et application du bruit <<Poivre \& Sel>>
\end{center}
\begin{center}
\includegraphics[scale=.34]{st3/Salt&Pepper_UNSET.jpg}\\
Figure 5. Calcul et suppression du bruit <<Poivre \& Sel>>
\end{center}
\end{figure}
\newpage \newpage
@ -362,7 +392,6 @@
\end{figure} \end{figure}
On remarque bien ici qu'une majorité des pixels ajoutés lors du bruitage a été proprement retirée, mais une partie reste bien visible. Celà est dû au fait que les pixels considérés comme bruit se voient appliquer un filtre moyen (couleur moyenne des voisins), mais que certains voisins peuvent être eux-aussi corrompus. De plus, certains pixels corrompus ne sont pas traités du fait qu'ils ont une teinte trop proche de la moyenne voisine. Il faut noter que lors du débruitage <<Poivre et Sel>> le paramètre \emph{borne} permettait d'éviter ce problème car nous avions des références absolues : le noir et le blanc. Nous avons donc décidé d'améliorer cet algorithme de débruitage (cf. \emph{Débruitage \begin{math}n^o\end{math}2}).\\\\ On remarque bien ici qu'une majorité des pixels ajoutés lors du bruitage a été proprement retirée, mais une partie reste bien visible. Celà est dû au fait que les pixels considérés comme bruit se voient appliquer un filtre moyen (couleur moyenne des voisins), mais que certains voisins peuvent être eux-aussi corrompus. De plus, certains pixels corrompus ne sont pas traités du fait qu'ils ont une teinte trop proche de la moyenne voisine. Il faut noter que lors du débruitage <<Poivre et Sel>> le paramètre \emph{borne} permettait d'éviter ce problème car nous avions des références absolues : le noir et le blanc. Nous avons donc décidé d'améliorer cet algorithme de débruitage (cf. \emph{Débruitage \begin{math}n^o\end{math}2}).\\\\
\newpage \newpage
@ -437,6 +466,17 @@
On remarque qu'avec cette nouvelle méthode, les contours sont moins dégradés et le bruit et d'autant plus diminué. Cet algorithme permet de différencier un contour d'un pixel bruité car la différence entre les poids statistiques écarte les deux cas. On remarque qu'avec cette nouvelle méthode, les contours sont moins dégradés et le bruit et d'autant plus diminué. Cet algorithme permet de différencier un contour d'un pixel bruité car la différence entre les poids statistiques écarte les deux cas.
\begin{figure}
\begin{center}
\includegraphics[scale=.38]{st3/Bernouilli_SET.jpg}\\
Figure 6. Création et application du bruit de Bernouilli
\end{center}
\begin{center}
\includegraphics[scale=.23]{st3/Bernouilli_UNSET.jpg}\\
Figure 7. Calcul et suppression du bruit de Bernouilli.
\end{center}
\end{figure}
\newpage \newpage
@ -498,6 +538,12 @@
On remarque bien ici que les contours subissent un lissage ce qui dégrade en majeure partie le rendu. Mais pour ce qui est du bruit additif Gaussien, le débruitage n'a jamais un très bon résultat sans l'utilisation de techniques avancées, nous remarquons donc un bon résultat comparé aux exemples vus sur internet. On remarque bien ici que les contours subissent un lissage ce qui dégrade en majeure partie le rendu. Mais pour ce qui est du bruit additif Gaussien, le débruitage n'a jamais un très bon résultat sans l'utilisation de techniques avancées, nous remarquons donc un bon résultat comparé aux exemples vus sur internet.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/Gaussian_SET.jpg}\\
Figure 8. Création et application du bruit gaussien.
\end{center}
\end{figure}
\newpage \newpage
@ -505,33 +551,20 @@
% ====================== % % ====================== %
% === PART 4 - VECTO === % % === PART 4 - VECTO === %
% ====================== % % ====================== %
\part*{Vectorisation pour la détection de contours} \part*{Optimisation du débruitage par la détection de contours}
% =================== % \textbf{Problème: }Nous avons remarqué précedemment que de manière générale après un débruitage, les contours de l'image deviennent irréguliers. Soit l'image subit un <<effet escalier>>, c'est à dire que certains pixels débruités ont une couleur trop éloignée de leur contexte ce qui donne l'impression que l'image n'est pas bien nettoyée. Soit l'image subit un effet de <<lissage>> ce qui dégrade les délimitations et contours présents.\\
% === SECT1 - BAS === % textbf{Solution: }La solution retenue s'appuie sur la \textbf{détection de contours}, cette partie vise à <<régulariser>> les contours.\\\\
% =================== % \textbf{Processus détaillé}
\section{Problème de base}
\textbf{Problème: }Nous avons remarqué précedemment que de manière générale après un débruitage, les contours de l'image deviennent irréguliers. Soit l'image subit un <<effet escalier>>, c'est à dire que certains pixels débruités ont une couleur trop éloignée de leur contexte ce qui donne l'impression que l'image n'est pas bien nettoyée. Soit l'image subit un effet de <<lissage>> ce qui dégrade les délimitations et contours présents.\\
\\\textbf{Solution: }La solution retenue s'appuie sur la \textbf{détection de contours}, cette partie vise à <<régulariser>> les contours.
% =================== %
% === SECT2 - DET === %
% =================== %
\section{Processus détaillé}
Nous avons décidé d'opter pour un algorithme en 6 étapes:\\ Nous avons décidé d'opter pour un algorithme en 6 étapes:\\
\textbf{Etape 1: }Premier nettoyage de l'image permettant d'optimiser la détection de contours.\\ \indent Etape 1: Premier nettoyage de l'image permettant d'optimiser la détection de contours.\\
\textbf{Etape 2: }Détection de contour afin de les indépendentialiser des formes pleines.\\ \indent Etape 2: Détection de contour afin de les indépendentialiser des formes pleines.\\
\textbf{Etape 3: }Débruitage de l'image d'origine.\\ \indent Etape 3: Débruitage de l'image d'origine.\\
\textbf{Etape 4: }Débruitage des contours de l'image d'origine à partir des contours.\\ \indent Etape 4: Débruitage des contours de l'image d'origine à partir des contours.\\
\textbf{Etape 5: }Superposition des contours débruités sur l'image débruitée.\\ \indent Etape 5: Superposition des contours débruités sur l'image débruitée.\\
\textbf{Etape 6: }Lissage minimal transitionnel de la superposition.\\ \indent Etape 6: Lissage minimal transitionnel de la superposition.\\\\
\textbf{Etape 1: }En premier lieu, il faut réduire suffisamment le bruit pour pouvoir correctement détecter les contours. Nous utilisons donc un débruitage standard adapté (méthodes vues précedemment).\\ \textbf{Etape 1: }En premier lieu, il faut réduire suffisamment le bruit pour pouvoir correctement détecter les contours. Nous utilisons donc un débruitage standard adapté (méthodes vues précedemment).\\
\textbf{Etape 2: }En second lieu, il faut isoler les contours, il existe plusieurs moyens de le faire:\\ \textbf{Etape 2: }En second lieu, il faut isoler les contours, il existe plusieurs moyens de le faire:\\
- soustraire l'image de base à l'image lissée (par filtre moyen)\\ - soustraire l'image de base à l'image lissée (par filtre moyen)\\
- utiliser un algorithme non-récursif d'indépendentisation de contour.\\ - utiliser un algorithme non-récursif d'indépendentisation de contour.\\
@ -548,6 +581,15 @@
\end{align*} \end{align*}
On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur\\ On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur\\
\begin{figure}[!h]
\begin{center}
\includegraphics[scale=.38]{st3/Convolution.jpg}\\
Figure 9. Implémentation du produit de convolution.
\end{center}
\end{figure}
\newpage
\emph{Méthode 2 - indépendentisation de contour}\\ \emph{Méthode 2 - indépendentisation de contour}\\
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 : 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 % indépendentisation de contour
@ -574,12 +616,10 @@
Détection sur forme 3 Détection sur forme 3
\end{minipage} \end{minipage}
\end{figure}\\ \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.\\\textbf{Etape 3: }Cette étape consiste à appliquer le débruitage standard à l'image d'origine.\\ 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.\\\textbf{Etape 3: }Consiste à appliquer le débruitage standard à l'image d'origine.\\
\textbf{Etape 4: }Cette étape consiste à appliquer le débruitage standard à l'image d'origine, mais uniquement sur les zones des contours récupérées à la deuxième étape.\\ \textbf{Etape 4: }Consiste à appliquer le débruitage standard à l'image d'origine, mais uniquement sur les zones des contours récupérées à la deuxième étape.\\
\textbf{Etape 5: }Cette étape correspond à la superposition des contours débruités sur l'image débruitée.\\ \textbf{Etape 5: }Correspond à la superposition des contours débruités sur l'image débruitée.\\
\textbf{Etape 6: }Cette étape correspond au lissage du contours des contours.\\ \textbf{Etape 6: }Correspond au lissage du contours des contours.\\
\newpage
% =================== % % =================== %
% === SECT3 - CON === % % === SECT3 - CON === %
@ -591,12 +631,25 @@
% === SECT4 - DET === % % === SECT4 - DET === %
% =================== % % =================== %
\section{Processus détaillé} \section{Processus détaillé}
ç
\indent \emph{Méthode 2 - indépendentisation de contour}\\ \indent \emph{Méthode 2 - indépendentisation de contour}\\
\newpage \newpage
\textbf{References}\\\\\-
[1] microsoft.com, Official Bitmap Header Format\\\\\-
[2] Mohammed M. Siddeq, Dr. Sadar Pirkhider Yaba, Using Discrete Wavelet Transform and Wiener filter for
Image De-nosing, Wasit Journal for Science \& Medicine, 2009\\\\\-
[3] Roger L. Easton, Jr., Fundamentals of Digital Image Processing, 22 November 2010\\\\\-
[4] Antoine Manzanera, ENSTA, Cours Master2 IAD, TERI : Traitement et
reconnaissance d'images\\\\\-
[5] UFRIMA, Détection de contours\\\\\-
[6] Image processing for space's pictures, Chapter 4\\\\\-
[7] Ecole polytechnique de Montréal, Mathématiques Appliquées et Génie Industriel, Applications des mathématiques : Détection des contours dune image, exercice 6\\\\\-
[8] Roman Garnett, Timothy Huegerich, Charles Chui, Fellow, IEEE, and Wenjie He*, Member, IEEE, A Universal Noise Removal Algorithm with an Impulse Detector\\\\\-
[9] IN\_GBM\_04\_CONTOURS, Détection de contours\\\\\-
[10] Peter Selinger, Potrace: a polygon-based tracing algorithm, September 20, 2003\\\\\-
\end{document} \end{document}

Binary file not shown.

View File

@ -73,7 +73,11 @@
\begin{figure}[!ht] \begin{figure}[!ht]
\centering \centering
\includegraphics{fileTree.jpg} \begin{minipage}[t]{8cm}
\centering
\includegraphics{st3/File_Architecture.jpg}
Figure 1. Structure de fichiers
\end{minipage}
\end{figure} \end{figure}
\begin{description} \begin{description}
@ -121,6 +125,14 @@
Soit le couple \begin{math}(x,y)\in\N^2\end{math}, les coordonnés d'un pixel dans I, tel que \begin{math}x\in[0;n_x[,\ et\ y\in[0;n_y[\end{math}.\\ Soit le couple \begin{math}(x,y)\in\N^2\end{math}, les coordonnés d'un pixel dans I, tel que \begin{math}x\in[0;n_x[,\ et\ y\in[0;n_y[\end{math}.\\
Soit \begin{math}\vec{u}\end{math} le vecteur associé à une unité de contour, tel que \begin{math}||\vec{u}|| = 1,\ et\ sa\ direction\ d =\frac{n\pi}{2}[2\pi]\ rad,\ avec\ n\in\N\end{math}.\\ Soit \begin{math}\vec{u}\end{math} le vecteur associé à une unité de contour, tel que \begin{math}||\vec{u}|| = 1,\ et\ sa\ direction\ d =\frac{n\pi}{2}[2\pi]\ rad,\ avec\ n\in\N\end{math}.\\
Soit \begin{math}K_n\end{math}, la matrice carré d'ordre \emph{n}. Par exemple \begin{math}K_3 = \begin{pmatrix}k_1&k_2&k_3\\k_4&k_5&k_6\\k_7&k_8&k_9\\\end{pmatrix}\end{math}\\\\ Soit \begin{math}K_n\end{math}, la matrice carré d'ordre \emph{n}. Par exemple \begin{math}K_3 = \begin{pmatrix}k_1&k_2&k_3\\k_4&k_5&k_6\\k_7&k_8&k_9\\\end{pmatrix}\end{math}\\\\
Afin de comparer les images nous avons implémenté le SNR, qui permet de donner calculer la qualité du débruitage.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/import_UTILITY.jpg}\\
Figure 2. Implémentation du SNR.
\end{center}
\end{figure}
\newpage \newpage
@ -233,6 +245,13 @@
Le \emph{bitmap} du fichier (matrice de pixels) peut avoir plusieurs formats qui sont propres au nombre de bits par pixels et dépendent de la \emph{palette}. De plus la matrice est dans l'ordre inverse, c'est à dire que le premier pixel est en fait le dernier, il convient donc d'inverser les lignes et les colonnes. De manière générale les pixels sont enregistrés en une succession de lignes. Le nombre d'octets de chaque ligne doit être un multiple de 4, est donc ajouté en fin de ligne un <<padding>> composé de 0 à 3 octets ayant pour valeur zéro. Le \emph{bitmap} du fichier (matrice de pixels) peut avoir plusieurs formats qui sont propres au nombre de bits par pixels et dépendent de la \emph{palette}. De plus la matrice est dans l'ordre inverse, c'est à dire que le premier pixel est en fait le dernier, il convient donc d'inverser les lignes et les colonnes. De manière générale les pixels sont enregistrés en une succession de lignes. Le nombre d'octets de chaque ligne doit être un multiple de 4, est donc ajouté en fin de ligne un <<padding>> composé de 0 à 3 octets ayant pour valeur zéro.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/BMPFile.jpg}
Figure 3. Structure du fichier BMPFile.py
\end{center}
\end{figure}
@ -309,6 +328,17 @@
\end{figure} \end{figure}
On remarque bien ici que les contours subissent un <<effet escalier>> ce qui dégrade en majeure partie le rendu. Nous avons réglé partiellement ce problème en ajoutant un lissage au processus de débruitage, mais le lissage réduit aussi la netteté de l'image. Par contre, les couleurs sont convenablement restituées, de même pour les teintes et contrastes. Il suffirait de traiter l'image en prenant en compte les contours, ce qui permettrait de gagner en qualité. On remarque bien ici que les contours subissent un <<effet escalier>> ce qui dégrade en majeure partie le rendu. Nous avons réglé partiellement ce problème en ajoutant un lissage au processus de débruitage, mais le lissage réduit aussi la netteté de l'image. Par contre, les couleurs sont convenablement restituées, de même pour les teintes et contrastes. Il suffirait de traiter l'image en prenant en compte les contours, ce qui permettrait de gagner en qualité.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/Salt&Pepper_SET.jpg}\\
Figure 4. Création et application du bruit <<Poivre \& Sel>>
\end{center}
\begin{center}
\includegraphics[scale=.34]{st3/Salt&Pepper_UNSET.jpg}\\
Figure 5. Calcul et suppression du bruit <<Poivre \& Sel>>
\end{center}
\end{figure}
\newpage \newpage
@ -362,7 +392,6 @@
\end{figure} \end{figure}
On remarque bien ici qu'une majorité des pixels ajoutés lors du bruitage a été proprement retirée, mais une partie reste bien visible. Celà est dû au fait que les pixels considérés comme bruit se voient appliquer un filtre moyen (couleur moyenne des voisins), mais que certains voisins peuvent être eux-aussi corrompus. De plus, certains pixels corrompus ne sont pas traités du fait qu'ils ont une teinte trop proche de la moyenne voisine. Il faut noter que lors du débruitage <<Poivre et Sel>> le paramètre \emph{borne} permettait d'éviter ce problème car nous avions des références absolues : le noir et le blanc. Nous avons donc décidé d'améliorer cet algorithme de débruitage (cf. \emph{Débruitage \begin{math}n^o\end{math}2}).\\\\ On remarque bien ici qu'une majorité des pixels ajoutés lors du bruitage a été proprement retirée, mais une partie reste bien visible. Celà est dû au fait que les pixels considérés comme bruit se voient appliquer un filtre moyen (couleur moyenne des voisins), mais que certains voisins peuvent être eux-aussi corrompus. De plus, certains pixels corrompus ne sont pas traités du fait qu'ils ont une teinte trop proche de la moyenne voisine. Il faut noter que lors du débruitage <<Poivre et Sel>> le paramètre \emph{borne} permettait d'éviter ce problème car nous avions des références absolues : le noir et le blanc. Nous avons donc décidé d'améliorer cet algorithme de débruitage (cf. \emph{Débruitage \begin{math}n^o\end{math}2}).\\\\
\newpage \newpage
@ -437,6 +466,17 @@
On remarque qu'avec cette nouvelle méthode, les contours sont moins dégradés et le bruit et d'autant plus diminué. Cet algorithme permet de différencier un contour d'un pixel bruité car la différence entre les poids statistiques écarte les deux cas. On remarque qu'avec cette nouvelle méthode, les contours sont moins dégradés et le bruit et d'autant plus diminué. Cet algorithme permet de différencier un contour d'un pixel bruité car la différence entre les poids statistiques écarte les deux cas.
\begin{figure}
\begin{center}
\includegraphics[scale=.38]{st3/Bernouilli_SET.jpg}\\
Figure 6. Création et application du bruit de Bernouilli
\end{center}
\begin{center}
\includegraphics[scale=.23]{st3/Bernouilli_UNSET.jpg}\\
Figure 7. Calcul et suppression du bruit de Bernouilli.
\end{center}
\end{figure}
\newpage \newpage
@ -498,6 +538,12 @@
On remarque bien ici que les contours subissent un lissage ce qui dégrade en majeure partie le rendu. Mais pour ce qui est du bruit additif Gaussien, le débruitage n'a jamais un très bon résultat sans l'utilisation de techniques avancées, nous remarquons donc un bon résultat comparé aux exemples vus sur internet. On remarque bien ici que les contours subissent un lissage ce qui dégrade en majeure partie le rendu. Mais pour ce qui est du bruit additif Gaussien, le débruitage n'a jamais un très bon résultat sans l'utilisation de techniques avancées, nous remarquons donc un bon résultat comparé aux exemples vus sur internet.
\begin{figure}
\begin{center}
\includegraphics[scale=.4]{st3/Gaussian_SET.jpg}\\
Figure 8. Création et application du bruit gaussien.
\end{center}
\end{figure}
\newpage \newpage
@ -505,33 +551,20 @@
% ====================== % % ====================== %
% === PART 4 - VECTO === % % === PART 4 - VECTO === %
% ====================== % % ====================== %
\part*{Vectorisation pour la détection de contours} \part*{Optimisation du débruitage par la détection de contours}
% =================== % \textbf{Problème: }Nous avons remarqué précedemment que de manière générale après un débruitage, les contours de l'image deviennent irréguliers. Soit l'image subit un <<effet escalier>>, c'est à dire que certains pixels débruités ont une couleur trop éloignée de leur contexte ce qui donne l'impression que l'image n'est pas bien nettoyée. Soit l'image subit un effet de <<lissage>> ce qui dégrade les délimitations et contours présents.\\
% === SECT1 - BAS === % textbf{Solution: }La solution retenue s'appuie sur la \textbf{détection de contours}, cette partie vise à <<régulariser>> les contours.\\\\
% =================== % \textbf{Processus détaillé}
\section{Problème de base}
\textbf{Problème: }Nous avons remarqué précedemment que de manière générale après un débruitage, les contours de l'image deviennent irréguliers. Soit l'image subit un <<effet escalier>>, c'est à dire que certains pixels débruités ont une couleur trop éloignée de leur contexte ce qui donne l'impression que l'image n'est pas bien nettoyée. Soit l'image subit un effet de <<lissage>> ce qui dégrade les délimitations et contours présents.\\
\\\textbf{Solution: }La solution retenue s'appuie sur la \textbf{détection de contours}, cette partie vise à <<régulariser>> les contours.
% =================== %
% === SECT2 - DET === %
% =================== %
\section{Processus détaillé}
Nous avons décidé d'opter pour un algorithme en 6 étapes:\\ Nous avons décidé d'opter pour un algorithme en 6 étapes:\\
\textbf{Etape 1: }Premier nettoyage de l'image permettant d'optimiser la détection de contours.\\ \indent Etape 1: Premier nettoyage de l'image permettant d'optimiser la détection de contours.\\
\textbf{Etape 2: }Détection de contour afin de les indépendentialiser des formes pleines.\\ \indent Etape 2: Détection de contour afin de les indépendentialiser des formes pleines.\\
\textbf{Etape 3: }Débruitage de l'image d'origine.\\ \indent Etape 3: Débruitage de l'image d'origine.\\
\textbf{Etape 4: }Débruitage des contours de l'image d'origine à partir des contours.\\ \indent Etape 4: Débruitage des contours de l'image d'origine à partir des contours.\\
\textbf{Etape 5: }Superposition des contours débruités sur l'image débruitée.\\ \indent Etape 5: Superposition des contours débruités sur l'image débruitée.\\
\textbf{Etape 6: }Lissage minimal transitionnel de la superposition.\\ \indent Etape 6: Lissage minimal transitionnel de la superposition.\\\\
\textbf{Etape 1: }En premier lieu, il faut réduire suffisamment le bruit pour pouvoir correctement détecter les contours. Nous utilisons donc un débruitage standard adapté (méthodes vues précedemment).\\ \textbf{Etape 1: }En premier lieu, il faut réduire suffisamment le bruit pour pouvoir correctement détecter les contours. Nous utilisons donc un débruitage standard adapté (méthodes vues précedemment).\\
\textbf{Etape 2: }En second lieu, il faut isoler les contours, il existe plusieurs moyens de le faire:\\ \textbf{Etape 2: }En second lieu, il faut isoler les contours, il existe plusieurs moyens de le faire:\\
- soustraire l'image de base à l'image lissée (par filtre moyen)\\ - soustraire l'image de base à l'image lissée (par filtre moyen)\\
- utiliser un algorithme non-récursif d'indépendentisation de contour.\\ - utiliser un algorithme non-récursif d'indépendentisation de contour.\\
@ -548,6 +581,15 @@
\end{align*} \end{align*}
On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur\\ On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur\\
\begin{figure}[!h]
\begin{center}
\includegraphics[scale=.38]{st3/Convolution.jpg}\\
Figure 9. Implémentation du produit de convolution.
\end{center}
\end{figure}
\newpage
\emph{Méthode 2 - indépendentisation de contour}\\ \emph{Méthode 2 - indépendentisation de contour}\\
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 : 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 % indépendentisation de contour
@ -574,12 +616,10 @@
Détection sur forme 3 Détection sur forme 3
\end{minipage} \end{minipage}
\end{figure}\\ \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.\\\textbf{Etape 3: }Cette étape consiste à appliquer le débruitage standard à l'image d'origine.\\ 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.\\\textbf{Etape 3: }Consiste à appliquer le débruitage standard à l'image d'origine.\\
\textbf{Etape 4: }Cette étape consiste à appliquer le débruitage standard à l'image d'origine, mais uniquement sur les zones des contours récupérées à la deuxième étape.\\ \textbf{Etape 4: }Consiste à appliquer le débruitage standard à l'image d'origine, mais uniquement sur les zones des contours récupérées à la deuxième étape.\\
\textbf{Etape 5: }Cette étape correspond à la superposition des contours débruités sur l'image débruitée.\\ \textbf{Etape 5: }Correspond à la superposition des contours débruités sur l'image débruitée.\\
\textbf{Etape 6: }Cette étape correspond au lissage du contours des contours.\\ \textbf{Etape 6: }Correspond au lissage du contours des contours.\\
\newpage
% =================== % % =================== %
% === SECT3 - CON === % % === SECT3 - CON === %
@ -591,12 +631,25 @@
% === SECT4 - DET === % % === SECT4 - DET === %
% =================== % % =================== %
\section{Processus détaillé} \section{Processus détaillé}
ç
\indent \emph{Méthode 2 - indépendentisation de contour}\\ \indent \emph{Méthode 2 - indépendentisation de contour}\\
\newpage \newpage
\textbf{References}\\\\\-
[1] microsoft.com, Official Bitmap Header Format\\\\\-
[2] Mohammed M. Siddeq, Dr. Sadar Pirkhider Yaba, Using Discrete Wavelet Transform and Wiener filter for
Image De-nosing, Wasit Journal for Science \& Medicine, 2009\\\\\-
[3] Roger L. Easton, Jr., Fundamentals of Digital Image Processing, 22 November 2010\\\\\-
[4] Antoine Manzanera, ENSTA, Cours Master2 IAD, TERI : Traitement et
reconnaissance d'images\\\\\-
[5] UFRIMA, Détection de contours\\\\\-
[6] Image processing for space's pictures, Chapter 4\\\\\-
[7] Ecole polytechnique de Montréal, Mathématiques Appliquées et Génie Industriel, Applications des mathématiques : Détection des contours dune image, exercice 6\\\\\-
[8] Roman Garnett, Timothy Huegerich, Charles Chui, Fellow, IEEE, and Wenjie He*, Member, IEEE, A Universal Noise Removal Algorithm with an Impulse Detector\\\\\-
[9] IN\_GBM\_04\_CONTOURS, Détection de contours\\\\\-
[10] Peter Selinger, Potrace: a polygon-based tracing algorithm, September 20, 2003\\\\\-
\end{document} \end{document}

BIN
dossier/st3/BMPFile.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1008 KiB

BIN
dossier/st3/Convolution.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB