Filtre de Canny terminé; #7

Open
Darkan wants to merge 1 commits from filter_canny into master
4 changed files with 241 additions and 59 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
imageEngine/images/ imageEngine/images/
imageEngine/test/ imageEngine/test/
imageEngine/__pycache__/ imageEngine/__pycache__/
imageEngine/filters/__pycache__/
imageEngine/test.py

View File

@ -1,39 +1,32 @@
from usefull_func import * from copy import deepcopy
from math import sqrt, atan2 from filters.usefull_func import *
from math import sqrt, atan2, pi
#En_cours...
def filtre_canny(img):
def norme_gradient(pixel1, pixel2): def filtreCanny(img, Th):
color_x = pixel1[0] Tl = Th / 2
color_y = pixel2[0]
norm = round(sqrt(color_x**2 + color_y**2)) filtred_image = filtre_gaussien(img)
norm = min(norm, 255)
grad = atan2(color_y, color_x) norme_gradient, angle_normale_gradient = calculGradient(filtred_image)
return norm, grad
def liste_normGrad(im1, im2): non_maxima = dltNoMaxima(norme_gradient, angle_normale_gradient)
liste = []
for j in range(len(im1)):
ligne = []
for i in range(len(im1[0])):
normGrad = norme_gradient(im1[j][i], im2[j][i])
ligne.append(normGrad)
liste.append(ligne)
return liste
if not is_greyscale(img): contours = seuillageHysteresis(non_maxima, angle_normale_gradient, Th, Tl)
img = greyscale(img)
mat_x = [[-1,0,1]] return contours
mat_y = [[1],[0],[-1]]
#lissage/suppression des bri """
tonitch marked this conversation as resolved
Review

ca ne fonctionne pas que tu l'ais mis en commentaire ?

ca ne fonctionne pas que tu l'ais mis en commentaire ?
Review

Le code est bon mais ça marche pas, j'ai sûrement quelques trucs à régler dans mon calcul de convolution. Du coup je le laisse ça en attendant d'avoir corriger le truc.

Le code est bon mais ça marche pas, j'ai sûrement quelques trucs à régler dans mon calcul de convolution. Du coup je le laisse ça en attendant d'avoir corriger le truc.
img_no_bruit = convolution_gauss(img) def filtreCannySemiAuto(img, centile):
Jx = convolution(img, mat_x) filtred_image = filtre_gaussien(img)
Jy = convolution(img, mat_y)
normGrad = liste_normGrad(Jx, Jy)
#Suppresion des non-maximum
norme_gradient, angle_normale_gradient = calculGradient(filtred_image)
non_maxima = dltNoMaxima(norme_gradient, angle_normale_gradient)
Th = calculTh(norme_gradient, centile)
Tl = Th / 2
contours = seuillageHysteresis(non_maxima, angle_normale_gradient, Th, Tl)
return contours
"""

View File

@ -1,5 +1,4 @@
from usefull_func import * from filters.usefull_func import *
def filtre_sobel(img): def filtre_sobel(img):

View File

@ -1,4 +1,5 @@
from math import sqrt from copy import deepcopy
from math import atan2, sqrt, pi
def greyscale(mat_img): def greyscale(mat_img):
gray_img = [] gray_img = []
@ -10,26 +11,29 @@ def greyscale(mat_img):
gray_img.append(lig) gray_img.append(lig)
return gray_img return gray_img
def appliquer_convolution(img, mat, i, j): def appliquer_convolution(img, mat, i, j):
somme = 0 somme = 0
for y in range(len(mat)): for x in range(len(mat)):
for x in range(len(mat[0])): for y in range(len(mat[0])):
pixel_i = i - (len(mat[0]) // 2) + x coord_i = i - (len(mat) // 2) + x
pixel_j = j - (len(mat) // 2) + y corrd_j = j - (len(mat[0]) // 2) + y
Review

Petite typo ici ?

Petite typo ici ?
pix = pixel(img, pixel_i, pixel_j) pix = pixel(img, coord_i, corrd_j)
somme += pix[0]*mat[y][x] somme += pix[0]*mat[x][y]
return min(max(somme,0), 255) return min(max(somme,0), 255)
def convolution(mat_img, mat): def convolution(mat_img, mat):
return_img = [] return_img = []
for j in range(len(mat_img)): for i in range(len(mat_img)):
ligne = [] ligne = []
for i in range(len(mat_img[0])): for j in range(len(mat_img[0])):
val = appliquer_convolution(mat_img, mat, i, j) val = appliquer_convolution(mat_img, mat, i, j)
ligne.append((val,)*3) ligne.append((val,)*3)
return_img.append(ligne) return_img.append(ligne)
return return_img return return_img
def is_greyscale(img): def is_greyscale(img):
_greyscale = True _greyscale = True
for ligne in img: for ligne in img:
@ -41,6 +45,7 @@ def is_greyscale(img):
break break
return _greyscale return _greyscale
def invert(img): def invert(img):
result_image = [] result_image = []
for ligne in img: for ligne in img:
@ -50,25 +55,28 @@ def invert(img):
result_image.append(result_ligne) result_image.append(result_ligne)
return result_image return result_image
def pixel(img, i, j, default=(0,0,0)): def pixel(img, i, j, default=(0,0,0)):
#i la colone et j la ligne #i la colone et j la ligne
Review

pourrais être x, y ou row, collumn pour être plus explicite?

pourrais être x, y ou row, collumn pour être plus explicite?
if 0 <= i < len(img[0]) and 0 <= j < len(img): if 0 <= i < len(img) and 0 <= j < len(img[0]):
return img[j][i] return img[i][j]
else: else:
return default return default
def reduction_bruit(img, mat, i, j): def reduction_bruit(img, mat, i, j):
somme = 0 somme = 0
for y in range(len(mat)): for x in range(len(mat)):
for x in range(len(mat[0])): for y in range(len(mat[0])):
pixel_i = i - (len(mat[0]) // 2) + x pixel_i = i - (len(mat) // 2) + x
pixel_j = j - (len(mat) // 2) + y pixel_j = j - (len(mat[0]) // 2) + y
pix = pixel(img, pixel_i, pixel_j) pix = pixel(img, pixel_i, pixel_j)
somme += pix[0]*mat[y][x] somme += pix[0]*mat[x][y]
normalise = round(somme) normalise = round(somme)
return normalise return normalise
def convolution_gauss(mat_img):
def filtre_gaussien(mat_img):
mat_gauss = [ mat_gauss = [
[2/159, 4/159, 5/159, 4/159,2/159], [2/159, 4/159, 5/159, 4/159,2/159],
Review

tricheur haha

tricheur haha
[4/159, 9/159,12/159, 9/159,4/159], [4/159, 9/159,12/159, 9/159,4/159],
@ -78,28 +86,208 @@ def convolution_gauss(mat_img):
] ]
return_img = [] return_img = []
for j in range(len(mat_img)): for i in range(len(mat_img)):
ligne = [] ligne = []
for i in range(len(mat_img[0])): for j in range(len(mat_img[0])):
val = reduction_bruit(mat_img, mat_gauss, i, j) val = reduction_bruit(mat_img, mat_gauss, i, j)
ligne.append((val,)*3) ligne.append((val,)*3)
return_img.append(ligne) return_img.append(ligne)
return return_img return return_img
def calcul_norme(pixel1, pixel2): def calcul_norme(pixel1, pixel2):
valeur = pixel1[0]**2 + pixel2[0]**2 valeur = pixel1[0]**2 + pixel2[0]**2
norm = round(sqrt(valeur)) norm = round(sqrt(valeur))
norm = int(min(norm, 255)) norm = int(min(norm, 255))
return norm return norm
def application_norme(im_x, im_y): def application_norme(im_x, im_y):
result_image = [] result_image = []
for j in range(len(im_x)): for i in range(len(im_x)):
ligne = [] ligne = []
for i in range(len(im_x[0])): for j in range(len(im_x[0])):
pixel1 = im_x[j][i] pixel1 = im_x[i][j]
pixel2 = im_y[j][i] pixel2 = im_y[i][j]
norme = calcul_norme(pixel1, pixel2) norme = calcul_norme(pixel1, pixel2)
ligne.append((norme,)*3) ligne.append((norme,)*3)
result_image.append(ligne) result_image.append(ligne)
return result_image return result_image
def calculGradient(filtred_image):
mask_x = [[1, 0, -1]]
mask_y = [[1],[0],[-1]]
Review

tu peux pas appliquer une seule convolution en fesant une matrice normalement ?

tu peux pas appliquer une seule convolution en fesant une matrice normalement ?
Review

Non, j'ai besoin de la valeur que donne les 2 matrices pour calculer le radient de l'angle de chaque pixel, et aussi calculer la norme.

Non, j'ai besoin de la valeur que donne les 2 matrices pour calculer le radient de l'angle de chaque pixel, et aussi calculer la norme.
Review

ha ouai je confonds haha

ha ouai je confonds haha
mask_gradient_x = convolution(filtred_image, mask_x)
mask_gradient_y = convolution(filtred_image, mask_y)
norme_gradient = copyNullMatrix(filtred_image)
angle_normal_gradient = copyNullMatrix(filtred_image)
for i in range(len(filtred_image)):
for j in range(len(filtred_image[0])):
Jx = mask_gradient_x[i][j][0]
Jy = mask_gradient_y[i][j][0]
norme_gradient[i][j] = sqrt(Jx**2 + Jy**2)
angle_temp = atan2(Jy,Jx)
angle_normal_gradient[i][j] = transform_angle(angle_temp)
return norme_gradient, angle_normal_gradient
def copyNullMatrix(mat):
Review

peut être fait en une ligne

nullmat = [[0 for i in j] for j in mat]

Je pense que c'est plus éfficace que de faire une copie puis ensuite de passer dans toute la matrice pour tout transformer

pire des cas tu peux le faire de manière plus explicite aussi

nullmat = list()
for i in range(len(mat)):
	nullmat.append(list())
	for _ in mat[i]:
    	nullmat[i].append(0)
return nullmat

ca fait la même chôse

peut être fait en une ligne ```python nullmat = [[0 for i in j] for j in mat] ``` Je pense que c'est plus éfficace que de faire une copie puis ensuite de passer dans toute la matrice pour tout transformer pire des cas tu peux le faire de manière plus explicite aussi ```python nullmat = list() for i in range(len(mat)): nullmat.append(list()) for _ in mat[i]: nullmat[i].append(0) return nullmat ``` ca fait la même chôse
Review

Je suis pas encore assez à l'aise avec python pour savoir faire des trucs comme ça 😢

Je suis pas encore assez à l'aise avec python pour savoir faire des trucs comme ça 😢
Review

alors la deuxième méthode est pour toi, ce que tu fais c'est une copie de de la matrice alors que tout ce que tu as besoin c'est de la taille ^^ ca va améliorer pas mal de faire la deuxième méthode que je t'ai montré

alors la deuxième méthode est pour toi, ce que tu fais c'est une copie de de la matrice alors que tout ce que tu as besoin c'est de la taille ^^ ca va améliorer pas mal de faire la deuxième méthode que je t'ai montré
nullMat = deepcopy(mat)
for i in range(len(nullMat)):
for j in range(len(nullMat[0])):
nullMat[i][j] = 0
return nullMat
def transform_angle(radient):
angle = radient * 180 / pi
if angle < 0:
angle += 180
#On veut que la valeur de l'angle soit 0, 45, 90 ou 135°
seuil_min_45 = 45/2
seuil_min_90 = (90+45)/2
seuil_min_135 = (135+90)/2
seuil_max_135 = (180+135)/2
if seuil_min_45 <= angle < seuil_min_90:
angle = 45
elif seuil_min_90 <= angle < seuil_min_135:
angle = 90
elif seuil_min_135 <= angle < seuil_max_135:
angle = 135
else:
angle = 0
return angle
def dltNoMaxima(norme_gradient, angle_normal_gradient):
non_maxima = copyNullMatrix(norme_gradient)
for i in range(len(non_maxima)):
for j in range(len(non_maxima[0])):
angle = angle_normal_gradient[i][j]
voisin1, voisin2 = norm_voisin(norme_gradient, angle, i, j)
if norme_gradient[i][j] < voisin1 or norme_gradient[i][j] < voisin2:
non_maxima[i][j] = 0
else:
non_maxima[i][j] = norme_gradient[i][j]
return non_maxima
def get_norm(norm_list, i, j):
norm = 0
if 0 <= i < len(norm_list) and 0 <= j < len(norm_list[0]):
norm = norm_list[i][j]
return norm
def norm_voisin(norm_list, angle, i, j):
voisin1 = None
voisin2 = None
if angle == 0:
voisin1 = get_norm(norm_list,i,j-1)
voisin2 = get_norm(norm_list,i,j+1)
elif angle == 45:
voisin2 = get_norm(norm_list,i-1,j+1)
voisin1 = get_norm(norm_list,i+1,j-1)
elif angle == 90:
voisin1 = get_norm(norm_list,i-1,j)
voisin2 = get_norm(norm_list,i+1,j)
elif angle == 135:
voisin2 = get_norm(norm_list,i-1,j-1)
voisin1 = get_norm(norm_list,i+1,j+1)
return voisin1, voisin2
def seuillageHysteresis(non_maxima, angle_normale_gradient, Th, Tl):
contours = deepcopy(non_maxima)
for i in range(len(angle_normale_gradient)):
for j in range(len(angle_normale_gradient[0])):
if non_maxima[i][j] > Th:
contours[i][j] = (255,)*3
elif non_maxima[i][j] < Tl:
contours[i][j] = (0,)*3
for i in range(len(angle_normale_gradient)):
for j in range(len(angle_normale_gradient[0])):
if Tl <= non_maxima[i][j] <= Th:
angle = angle_normale_gradient[i][j] + 90
if angle >= 180:
angle -= 180
voisin1, voisin2 = norm_voisin(non_maxima, angle, i, j)
if voisin1 > Th and voisin2 > Th:
contours[i][j] = (255,)*3
else:
contours[i][j] = (0,)*3
return contours
"""
def calculTh(norme_gradient, centile):
histogramme, pas = calculHistogram(norme_gradient)
fonctionRepartition = calculFonctionRepartition(histogramme)
nbrPixels = len(norme_gradient)*len(norme_gradient[0])
pivot = nbrPixels * centile
Th_index = 0
for i in range(len(fonctionRepartition)):
if (pivot - fonctionRepartition[0][Th_index]) > (pivot - fonctionRepartition[0][i]) and (pivot - fonctionRepartition[i] > 0):
Th_index = i
Th = pas * (Th_index - 1)
return Th
def calculHistogram(norme_gradient):
norme_max = Maxi(norme_gradient)
norme_min = Minim(norme_gradient)
ecart = norme_max - norme_min
nb_pas = 1000
pas = ecart / (nb_pas - 1)
histogram = [[0]*nb_pas]
for i in range(len(norme_gradient)):
for j in range(len(norme_gradient[0])):
valeur_pixel = norme_gradient[i][j]
position = floor((valeur_pixel - norme_min) / pas)
histogram[0][position] += 1
return histogram, pas
def calculFonctionRepartition(histogram):
fonctionRepartition = deepcopy(histogram)
for i in range(1, len(fonctionRepartition[0])):
fonctionRepartition[0][i] = fonctionRepartition[0][i-1] + histogram[0][i-1]
return fonctionRepartition
def Maxi(mat):
mx = 0
for i in range(len(mat)):
for j in range(len(mat[0])):
if mat[i][j] > mx:
mx = mat[i][j]
return mx
def Minim(mat):
mn = 1000
Review

en vrai ca devrais pas poser de problème mais tu peux le faire de manière différente:

mn = mat[0][0]
for i in mat:
	for j in i:
    	if(i < mn):
        	mn = j
return mn

c'est un détail parce que je pense pas que tu vas avoir des valeurs supérieurs à 1000 dans tes matrice mais techniquement on sais jamais, ca peut être plus sur

en vrai ca devrais pas poser de problème mais tu peux le faire de manière différente: ```python mn = mat[0][0] for i in mat: for j in i: if(i < mn): mn = j return mn ``` c'est un détail parce que je pense pas que tu vas avoir des valeurs supérieurs à 1000 dans tes matrice mais techniquement on sais jamais, ca peut être plus sur
for i in range(len(mat)):
for j in range(len(mat[0])):
if mat[i][j] < mn:
mn = mat[i][j]
return mn
"""