Filtre de Canny terminé; #7
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
|||||||
imageEngine/images/
|
imageEngine/images/
|
||||||
imageEngine/test/
|
imageEngine/test/
|
||||||
imageEngine/__pycache__/
|
imageEngine/__pycache__/
|
||||||
|
imageEngine/filters/__pycache__/
|
||||||
|
imageEngine/test.py
|
@ -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
|
|||||||
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
|
||||||
|
"""
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from usefull_func import *
|
from filters.usefull_func import *
|
||||||
|
|
||||||
|
|
||||||
def filtre_sobel(img):
|
def filtre_sobel(img):
|
||||||
|
|
||||||
|
@ -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
|
||||||
tonitch
commented
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
|
||||||
tonitch
commented
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],
|
||||||
tonitch
commented
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]]
|
||||||
tonitch
commented
tu peux pas appliquer une seule convolution en fesant une matrice normalement ? tu peux pas appliquer une seule convolution en fesant une matrice normalement ?
Darkan
commented
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.
tonitch
commented
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):
|
||||||
tonitch
commented
peut être fait en une ligne
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
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
Darkan
commented
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 😢
tonitch
commented
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
|
||||||
tonitch
commented
en vrai ca devrais pas poser de problème mais tu peux le faire de manière différente:
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
|
||||||
|
"""
|
||||||
|
ca ne fonctionne pas que tu l'ais mis en commentaire ?
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.