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/test/
imageEngine/__pycache__/
imageEngine/filters/__pycache__/
imageEngine/test.py

View File

@ -1,39 +1,32 @@
from usefull_func import *
from math import sqrt, atan2
from copy import deepcopy
from filters.usefull_func import *
from math import sqrt, atan2, pi
#En_cours...
def filtre_canny(img):
def norme_gradient(pixel1, pixel2):
color_x = pixel1[0]
color_y = pixel2[0]
def filtreCanny(img, Th):
Tl = Th / 2
norm = round(sqrt(color_x**2 + color_y**2))
norm = min(norm, 255)
filtred_image = filtre_gaussien(img)
grad = atan2(color_y, color_x)
return norm, grad
norme_gradient, angle_normale_gradient = calculGradient(filtred_image)
def liste_normGrad(im1, im2):
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
non_maxima = dltNoMaxima(norme_gradient, angle_normale_gradient)
if not is_greyscale(img):
img = greyscale(img)
contours = seuillageHysteresis(non_maxima, angle_normale_gradient, Th, Tl)
mat_x = [[-1,0,1]]
mat_y = [[1],[0],[-1]]
return contours
#lissage/suppression des bri
img_no_bruit = convolution_gauss(img)
Jx = convolution(img, mat_x)
Jy = convolution(img, mat_y)
normGrad = liste_normGrad(Jx, Jy)
#Suppresion des non-maximum
"""
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.
def filtreCannySemiAuto(img, centile):
filtred_image = filtre_gaussien(img)
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):

View File

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

Petite typo ici ?

Petite typo ici ?
pix = pixel(img, coord_i, corrd_j)
somme += pix[0]*mat[x][y]
return min(max(somme,0), 255)
def convolution(mat_img, mat):
return_img = []
for j in range(len(mat_img)):
for i in range(len(mat_img)):
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)
ligne.append((val,)*3)
return_img.append(ligne)
return return_img
def is_greyscale(img):
_greyscale = True
for ligne in img:
@ -41,6 +45,7 @@ def is_greyscale(img):
break
return _greyscale
def invert(img):
result_image = []
for ligne in img:
@ -50,25 +55,28 @@ def invert(img):
result_image.append(result_ligne)
return result_image
def pixel(img, i, j, default=(0,0,0)):
#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):
return img[j][i]
if 0 <= i < len(img) and 0 <= j < len(img[0]):
return img[i][j]
else:
return default
def reduction_bruit(img, mat, i, j):
somme = 0
for y in range(len(mat)):
for x in range(len(mat[0])):
pixel_i = i - (len(mat[0]) // 2) + x
pixel_j = j - (len(mat) // 2) + y
for x in range(len(mat)):
for y in range(len(mat[0])):
pixel_i = i - (len(mat) // 2) + x
pixel_j = j - (len(mat[0]) // 2) + y
pix = pixel(img, pixel_i, pixel_j)
somme += pix[0]*mat[y][x]
somme += pix[0]*mat[x][y]
normalise = round(somme)
return normalise
def convolution_gauss(mat_img):
def filtre_gaussien(mat_img):
mat_gauss = [
[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],
@ -78,28 +86,208 @@ def convolution_gauss(mat_img):
]
return_img = []
for j in range(len(mat_img)):
for i in range(len(mat_img)):
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)
ligne.append((val,)*3)
return_img.append(ligne)
return return_img
def calcul_norme(pixel1, pixel2):
valeur = pixel1[0]**2 + pixel2[0]**2
norm = round(sqrt(valeur))
norm = int(min(norm, 255))
return norm
def application_norme(im_x, im_y):
result_image = []
for j in range(len(im_x)):
for i in range(len(im_x)):
ligne = []
for i in range(len(im_x[0])):
pixel1 = im_x[j][i]
pixel2 = im_y[j][i]
for j in range(len(im_x[0])):
pixel1 = im_x[i][j]
pixel2 = im_y[i][j]
norme = calcul_norme(pixel1, pixel2)
ligne.append((norme,)*3)
result_image.append(ligne)
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
"""