test
|
@ -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;
|
After Width: | Height: | Size: 257 KiB |
After Width: | Height: | Size: 227 KiB |
Before Width: | Height: | Size: 352 KiB |
Before Width: | Height: | Size: 221 KiB |
Before Width: | Height: | Size: 416 KiB |
Before Width: | Height: | Size: 452 KiB |
Before Width: | Height: | Size: 768 KiB |
Before Width: | Height: | Size: 768 KiB |
After Width: | Height: | Size: 257 KiB |
|
@ -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
|
|
@ -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()
|
|
@ -231,7 +231,8 @@ def interfaceLoop():
|
|||
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 ] -');
|
||||
print '- [ OR PRESS "S" TO SAVE ] -';
|
||||
loopKey = raw_input(': ');
|
||||
|
||||
if( loopKey == 'q' or loopKey == 'Q' ):
|
||||
exit();
|
||||
|
|
|
@ -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();
|
After Width: | Height: | Size: 227 KiB |
After Width: | Height: | Size: 257 KiB |
22
code/todo.md
|
@ -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 |
|
||||
+------+
|
|
@ -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] )
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
@ -73,9 +73,13 @@
|
|||
|
||||
\begin{figure}[!ht]
|
||||
\centering
|
||||
\includegraphics{fileTree.jpg}
|
||||
\begin{minipage}[t]{8cm}
|
||||
\centering
|
||||
\includegraphics{st3/File_Architecture.jpg}
|
||||
Figure 1. Structure de fichiers
|
||||
\end{minipage}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\begin{description}
|
||||
\item \textbf{main.py} \hfill \\
|
||||
Programme principal, il affiche une interface (en console) permettant d'éxécuter une des opérations disponibles.
|
||||
|
@ -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 \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}\\\\
|
||||
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
|
||||
|
@ -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.
|
||||
|
||||
|
||||
\begin{figure}
|
||||
\begin{center}
|
||||
\includegraphics[scale=.4]{st3/BMPFile.jpg}
|
||||
Figure 3. Structure du fichier BMPFile.py
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -308,6 +327,17 @@
|
|||
\end{minipage}
|
||||
\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é.
|
||||
|
||||
\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
|
||||
|
||||
|
@ -362,7 +392,6 @@
|
|||
\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}).\\\\
|
||||
|
||||
|
||||
\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.
|
||||
|
||||
|
||||
\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
|
||||
|
||||
|
@ -497,7 +537,13 @@
|
|||
\end{figure}
|
||||
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
|
||||
|
||||
|
@ -505,33 +551,20 @@
|
|||
% ====================== %
|
||||
% === PART 4 - VECTO === %
|
||||
% ====================== %
|
||||
\part*{Vectorisation pour la détection de contours}
|
||||
\part*{Optimisation du débruitage par la détection de contours}
|
||||
|
||||
|
||||
% =================== %
|
||||
% === SECT1 - BAS === %
|
||||
% =================== %
|
||||
\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é}
|
||||
\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.\\\\
|
||||
\textbf{Processus détaillé}
|
||||
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.\\
|
||||
\textbf{Etape 2: }Détection de contour afin de les indépendentialiser des formes pleines.\\
|
||||
\textbf{Etape 3: }Débruitage de l'image d'origine.\\
|
||||
\textbf{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.\\
|
||||
\textbf{Etape 6: }Lissage minimal transitionnel de la superposition.\\
|
||||
|
||||
|
||||
\indent Etape 1: Premier nettoyage de l'image permettant d'optimiser la détection de contours.\\
|
||||
\indent Etape 2: Détection de contour afin de les indépendentialiser des formes pleines.\\
|
||||
\indent Etape 3: Débruitage de l'image d'origine.\\
|
||||
\indent Etape 4: Débruitage des contours de l'image d'origine à partir des contours.\\
|
||||
\indent Etape 5: Superposition des contours débruités sur l'image débruitée.\\
|
||||
\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 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)\\
|
||||
- utiliser un algorithme non-récursif d'indépendentisation de contour.\\
|
||||
|
@ -548,6 +581,15 @@
|
|||
\end{align*}
|
||||
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}\\
|
||||
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
|
||||
|
@ -574,12 +616,10 @@
|
|||
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.\\\textbf{Etape 3: }Cette étape 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 5: }Cette étape 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.\\
|
||||
|
||||
\newpage
|
||||
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: }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: }Correspond à la superposition des contours débruités sur l'image débruitée.\\
|
||||
\textbf{Etape 6: }Correspond au lissage du contours des contours.\\
|
||||
|
||||
% =================== %
|
||||
% === SECT3 - CON === %
|
||||
|
@ -591,12 +631,25 @@
|
|||
% === SECT4 - DET === %
|
||||
% =================== %
|
||||
\section{Processus détaillé}
|
||||
|
||||
ç
|
||||
\indent \emph{Méthode 2 - indépendentisation de contour}\\
|
||||
|
||||
|
||||
\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 d’une 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}
|
|
@ -73,9 +73,13 @@
|
|||
|
||||
\begin{figure}[!ht]
|
||||
\centering
|
||||
\includegraphics{fileTree.jpg}
|
||||
\begin{minipage}[t]{8cm}
|
||||
\centering
|
||||
\includegraphics{st3/File_Architecture.jpg}
|
||||
Figure 1. Structure de fichiers
|
||||
\end{minipage}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\begin{description}
|
||||
\item \textbf{main.py} \hfill \\
|
||||
Programme principal, il affiche une interface (en console) permettant d'éxécuter une des opérations disponibles.
|
||||
|
@ -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 \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}\\\\
|
||||
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
|
||||
|
@ -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.
|
||||
|
||||
|
||||
\begin{figure}
|
||||
\begin{center}
|
||||
\includegraphics[scale=.4]{st3/BMPFile.jpg}
|
||||
Figure 3. Structure du fichier BMPFile.py
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -308,6 +327,17 @@
|
|||
\end{minipage}
|
||||
\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é.
|
||||
|
||||
\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
|
||||
|
||||
|
@ -362,7 +392,6 @@
|
|||
\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}).\\\\
|
||||
|
||||
|
||||
\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.
|
||||
|
||||
|
||||
\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
|
||||
|
||||
|
@ -497,7 +537,13 @@
|
|||
\end{figure}
|
||||
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
|
||||
|
||||
|
@ -505,33 +551,20 @@
|
|||
% ====================== %
|
||||
% === PART 4 - VECTO === %
|
||||
% ====================== %
|
||||
\part*{Vectorisation pour la détection de contours}
|
||||
\part*{Optimisation du débruitage par la détection de contours}
|
||||
|
||||
|
||||
% =================== %
|
||||
% === SECT1 - BAS === %
|
||||
% =================== %
|
||||
\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é}
|
||||
\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.\\\\
|
||||
\textbf{Processus détaillé}
|
||||
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.\\
|
||||
\textbf{Etape 2: }Détection de contour afin de les indépendentialiser des formes pleines.\\
|
||||
\textbf{Etape 3: }Débruitage de l'image d'origine.\\
|
||||
\textbf{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.\\
|
||||
\textbf{Etape 6: }Lissage minimal transitionnel de la superposition.\\
|
||||
|
||||
|
||||
\indent Etape 1: Premier nettoyage de l'image permettant d'optimiser la détection de contours.\\
|
||||
\indent Etape 2: Détection de contour afin de les indépendentialiser des formes pleines.\\
|
||||
\indent Etape 3: Débruitage de l'image d'origine.\\
|
||||
\indent Etape 4: Débruitage des contours de l'image d'origine à partir des contours.\\
|
||||
\indent Etape 5: Superposition des contours débruités sur l'image débruitée.\\
|
||||
\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 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)\\
|
||||
- utiliser un algorithme non-récursif d'indépendentisation de contour.\\
|
||||
|
@ -548,6 +581,15 @@
|
|||
\end{align*}
|
||||
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}\\
|
||||
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
|
||||
|
@ -574,12 +616,10 @@
|
|||
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.\\\textbf{Etape 3: }Cette étape 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 5: }Cette étape 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.\\
|
||||
|
||||
\newpage
|
||||
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: }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: }Correspond à la superposition des contours débruités sur l'image débruitée.\\
|
||||
\textbf{Etape 6: }Correspond au lissage du contours des contours.\\
|
||||
|
||||
% =================== %
|
||||
% === SECT3 - CON === %
|
||||
|
@ -591,12 +631,25 @@
|
|||
% === SECT4 - DET === %
|
||||
% =================== %
|
||||
\section{Processus détaillé}
|
||||
|
||||
ç
|
||||
\indent \emph{Méthode 2 - indépendentisation de contour}\\
|
||||
|
||||
|
||||
\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 d’une 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}
|
After Width: | Height: | Size: 683 KiB |
After Width: | Height: | Size: 335 KiB |
After Width: | Height: | Size: 1008 KiB |
After Width: | Height: | Size: 658 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 364 KiB |
After Width: | Height: | Size: 241 KiB |
After Width: | Height: | Size: 902 KiB |
After Width: | Height: | Size: 410 KiB |