This commit is contained in:
xdrm-brackets 2015-10-05 18:07:59 +02:00
parent 842c20a917
commit 2aed1441fb
15 changed files with 454 additions and 11 deletions

224
code/BMPFile.readme Normal file
View File

@ -0,0 +1,224 @@
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] )

69
code/Noise.readme Normal file
View File

@ -0,0 +1,69 @@
Classes:
/******************/
/** COLORIZATION **/
/******************/
Principe: colorer en modifiant les pixels (n&b) dans un ton (teinte) précisée
restitue la contraste mais recentre la couleur autour de la teinte
/************ ALGO **************/
i = 50 // incertitude
t = RGBPixel(1,2,3) // teinte souhaitée
p = RGBPixel(1,2,3) // couleur actuelle
/************ CODE **************/
def colorize(pixel, tint):
/*****************/
/** SHAPIZATION **/
/*****************/
Principe: récupérer une forme par récurrence
Ajouter les 8 bits périphériques du pixel courant s'il existe et s'il a des couleurs pas trop éloignées des précédentes
/************ ALGO **************/
/************ CODE **************/
def getShape(self, coords, pixelMap, pixelList ): # return PixelList
# coords = [lastx, lasty, x, y]
width = len( pixelMap[0] )
height = len( pixelMap )
lastx = coords[0]
lasty = coords[1]
x = coords[2]
y = coords[3]
newCoords = [x, y]
# si le pixel existe (pas de dépassement de la pixelMap)
if x<width and x>=0 and y<height and y>=0:
already = False;
for i in range(0, len(pixelList)):
if pixelList[i] == pixelMap[y][x]:
already = True;
break
# si le pixel n'est pas déjà dans le tableau
if not already:
pixelMap[y][x].setRGB(255,0,0); # debug, tout rouge
pixelList.append( pixelMap[y][x] ) # ajout au tableau
self.getShape(newCoords+[x-1, y+1], pixelMap, pixelList) # 1
self.getShape(newCoords+[x, y+1], pixelMap, pixelList) # 2
self.getShape(newCoords+[x+1, y+1], pixelMap, pixelList) # 3
self.getShape(newCoords+[x-1, y], pixelMap, pixelList) # 4
# current pixel
self.getShape(newCoords+[x+1, y], pixelMap, pixelList) # 6
self.getShape(newCoords+[x-1, y-1], pixelMap, pixelList) # 7
self.getShape(newCoords+[x, y-1], pixelMap, pixelList) # 8
self.getShape(newCoords+[x+1, y-1], pixelMap, pixelList) # 9

65
code/bmp.py Normal file
View File

@ -0,0 +1,65 @@
# ~*~ encoding: utf-8 ~*~ #
###########################
# TRAITEMENT D'IMAGES #
###########################
# classes
from BMPFile import *
from Noise import *
import random
import sys
def testFileIntegrity():
# lecture du fichier
with open( sys.argv[1] ) as file:
binFile = file.read()
# Instanciation du BMPFile
img = BMPFile()
# Instanciation du NoiseObject
noise = Noise();
# Parsing
img.parse( binFile );
noise.SaltAndPepper_set(10, img.content.map)
# Unparsing
img.unparse(newBpp=24)
print img.binData
def testManualCreation():
img = BMPFile()
for y in range(0, 100):
img.content.map.append( [] )
for x in range(0, 100):
img.content.map[y].append( RGBPixel(
random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255),
bpp=24
) );
img.unparse();
print img.binData
# MAIN
#testManualCreation()
testFileIntegrity()

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

View File

@ -68,6 +68,7 @@ print "| 43) %s |" % exactLength("Prewitt", 21, -1)
print "| 44) %s |" % exactLength("Sobel", 21, -1)
print "| 45) %s |" % exactLength("Convolution", 21, -1)
print "| 46) %s |" % exactLength("bichrome", 21, -1)
print "| 47) %s |" % exactLength("Passe Haut", 21, -1)
print "+---------------------------+"
print
while True:
@ -207,6 +208,9 @@ elif action == 45:
elif action == 46:
print startStr
testBichrome() # teste le passage au bichromatique
elif action == 47:
print startStr
testHighPass() # teste le filtre passe haut
else:
print "Wrong choice"

BIN
code/new.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

View File

@ -1453,3 +1453,48 @@ def testBichrome():
# teste le filtre de passe haut sur d'une image #
#################################################
# @sysarg 1 le fichier d'origine
# @stsarg 2 le fichier de sortie (filtré)
#
# @history
# Parse le fichier d'origine
# Applique le filtre
# Unparse l'image et l'enregistre dans le fichier de sortie
def testHighPass():
t = Timer();
# lecture du fichier
print "| Reading Image |",; t.reset();
with open( sys.argv[1] ) as file:
binFile = file.read()
print "%s |" % (t.get())
img = BMPFile(); # Instanciation du BMPFile
# Parsing
print "| Parsing file |",; t.reset();
img.parse( binFile );
print "%s |" % (t.get())
print "| Application du filtre |",; t.reset();
img.content.map = FX.Filter.HighPass(img.content.map);
print "%s |" % (t.get())
# Unparsing
print "| Unparsing file |",; t.reset();
img.unparse()
print "%s |" % (t.get())
# image to stdout
print "| Writing file |",; t.reset();
img.write( sys.argv[2] )
print "%s |" % (t.get())

View File

@ -19,13 +19,13 @@ class Filter:
# Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant :
#
# 1 1 1
# 1 0 1
# 1 1 1
# 1 1 1
#
def averageFilter(self, pixelMap):
return self.Convolution(pixelMap, kernel=[
[1, 1, 1],
[1, 0, 1],
[1, 1, 1],
[1, 1, 1]
] );
@ -84,6 +84,25 @@ class Filter:
] );
# Applique un filtre passe-haut à l'image de base vers l'image de sortie #
##########################################################################
# @param pixelMap Matrice de pixel à traiter (modifier)
#
#
# Celà revient à effectuer un produit de convolution avec le noyau de conv. suivant :
#
# -1 0 1
# -2 0 2
# -1 0 1
#
def HighPass(self, pixelMap):
return self.Convolution(pixelMap, kernel=[
[ 0, -1, 0],
[-1, 5, -1],
[ 0, -1, 0]
] );

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

View File

@ -548,15 +548,32 @@
On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur\\
\indent \emph{Méthode 2 - indépendentisation de contour}\\
L'image est lissée avec un filtre moyen. Nous effectuons un produit de convolution (noté \begin{math}\otimes\end{math}) avec l'image \emph{I} et le noyau tel que défini :
\begin{align*}
I_{lisse} = I\ \otimes\ \frac{1}{8} \begin{pmatrix}
1 & 1 & 1\\
1 & 0 & 1\\
1 & 1 & 1
\end{pmatrix}
\end{align*}
On effectue ensuite la soustraction matricielle afin de mettre les contours en valeur
Un algorithme lance sur chaque pixel de l'image un "envahisseur", c'est-à-dire un algorithme qui référencie chaque pixel considéré dans la même forme que le pixel de départ. par exemple, on obtient le résultat ci-dessous en essayant de récupérer les formes noires uniquement :
% indépendentisation de contour
\begin{figure}[!ht]
\centering
\begin{minipage}[t]{3.5cm}
\centering
\includegraphics[width=3.5cm]{Vectorization/shape.jpg}
Image originale
\end{minipage}
\begin{minipage}[t]{3.5cm}
\centering
\includegraphics[width=3.5cm]{Vectorization/shapeDetection1.jpg}
Détection sur forme 1
\end{minipage}
\begin{minipage}[t]{3.5cm}
\centering
\includegraphics[width=3.5cm]{Vectorization/shapeDetection2.jpg}
Détection sur forme 2
\end{minipage}
\begin{minipage}[t]{3.5cm}
\centering
\includegraphics[width=3.5cm]{Vectorization/shapeDetection3.jpg}
Détection sur forme 3
\end{minipage}
\end{figure}\\
Les résultats sont corrects mais le traitement devient vite très long, le temps d'éxécution moyen pour ces résultats est de 20 secondes. Nous avons donc décidé de créer un nouvel algorithme qui lui récupérerait uniquement les contours.
\newpage