-
Notifications
You must be signed in to change notification settings - Fork 0
/
psoEdgeImageProcessing.py
192 lines (150 loc) · 7.37 KB
/
psoEdgeImageProcessing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import cv2
import numpy as np
import pywt
import matplotlib.pyplot as plt
# Clase para las partículas en PSO
class Particle:
def __init__(self, subband):
self.position = np.array([np.random.randint(1, subband.shape[0]-1),
np.random.randint(1, subband.shape[1]-1)], dtype='float64')
self.velocity = np.random.uniform(-1, 1, size=2)
self.best_position = self.position.copy()
self.best_value = objective_function(self.position, subband)
def update_velocity(self, global_best_position, w, c1, c2):
r1 = np.random.rand()
r2 = np.random.rand()
cognitive_component = c1 * r1 * (self.best_position - self.position)
social_component = c2 * r2 * (global_best_position - self.position)
self.velocity = w * self.velocity + cognitive_component + social_component
def update_position(self, subband):
self.position += self.velocity
self.position = np.clip(self.position, [1, 1], [subband.shape[0]-2, subband.shape[1]-2])
current_value = objective_function(self.position, subband)
if current_value > self.best_value:
self.best_position = self.position.copy()
self.best_value = current_value
# Función objetivo basada en la magnitud del gradiente
def objective_function(particle_position, subband):
i, j = particle_position.astype(int)
gradient_magnitude = subband[i, j]
# Derivadas de píxeles vecinos (clusters locales)
neighbors = [
(i-1, j-1), (i-1, j), (i-1, j+1),
(i, j-1), (i, j+1),
(i+1, j-1), (i+1, j), (i+1, j+1)
]
local_gradient = 0
for ni, nj in neighbors:
if 0 <= ni < subband.shape[0] and 0 <= nj < subband.shape[1]:
local_gradient += abs(gradient_magnitude - subband[ni, nj])
return local_gradient # Maximizar la diferencia en el cluster
# Función para aplicar DWT y descomponer la imagen en subbandas
def dwt_decomposition(image):
coeffs = pywt.dwt2(image, 'haar')
LL, (LH, HL, HH) = coeffs
return LL, LH, HL, HH, coeffs
# PSO aplicado en cada subbanda de la imagen
def pso_on_subband(subband, subband_name, num_particles=30, iterations=100):
particles = [Particle(subband) for _ in range(num_particles)]
global_best_position = particles[0].best_position.copy()
global_best_value = particles[0].best_value
# Lista para almacenar el progreso del valor global óptimo
global_best_progress = []
for i in range(iterations):
for particle in particles:
# Ajustes en los parámetros de PSO: w = 0.4, c1 = 2.5, c2 = 2.5
particle.update_velocity(global_best_position, w=0.4, c1=2.5, c2=2.5)
particle.update_position(subband)
if particle.best_value > global_best_value:
global_best_position = particle.best_position.copy()
global_best_value = particle.best_value
# Almacenar el valor global óptimo actual
global_best_progress.append(global_best_value)
print(f"Iteración {i}, Valor global óptimo: {global_best_value}")
# Graficar el progreso del valor global óptimo con el nombre de la subbanda
plt.plot(global_best_progress)
plt.title(f"Progreso del valor global óptimo durante PSO en {subband_name}")
plt.xlabel("Iteraciones")
plt.ylabel("Valor del mejor global")
plt.grid()
plt.show()
return particles, global_best_position
# Función de umbralización automática
def automatic_thresholding(image):
# Convertir la imagen de flotante a uint8
image_scaled = np.uint8(255 * (image - np.min(image)) / (np.max(image) - np.min(image)))
_, thresholded_image = cv2.threshold(image_scaled, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
return thresholded_image
# Función principal para la detección de bordes usando DWT y PSO
def edge_detection_with_dwt_pso(image):
# Descomposición de la imagen en subbandas
LL, LH, HL, HH, coeffs = dwt_decomposition(image)
# Aplicar PSO a cada subbanda
_, best_LL = pso_on_subband(HH, "Subbanda LL")
_, best_LH = pso_on_subband(LH, "Subbanda LH")
_, best_HL = pso_on_subband(HL, "Subbanda HL")
_, best_HH = pso_on_subband(HH, "Subbanda HH")
# Crear imágenes con bordes optimizados en las subbandas
edges_LL = np.zeros_like(LL)
edges_LH = np.zeros_like(LH)
edges_HL = np.zeros_like(HL)
edges_HH = np.zeros_like(HH)
edges_LL[best_LL[0].astype(int), best_LL[1].astype(int)] = 255
edges_LH[best_LH[0].astype(int), best_LH[1].astype(int)] = 255
edges_HL[best_HL[0].astype(int), best_HL[1].astype(int)] = 255
edges_HH[best_HH[0].astype(int), best_HH[1].astype(int)] = 255
# Reconstrucción de la imagen con iDWT (Transformada Inversa)
reconstructed_image = pywt.idwt2((edges_LL, (LH, HL, LH)), 'haar')
# Umbralización automática para obtener bordes finales
final_edges = automatic_thresholding(reconstructed_image)
return final_edges
# Cargar la imagen de entrada en escala de grises
img= cv2.imread('C:/Users/escob/OneDrive/Escritorio/CAC/images/McLarenW1.jpg', cv2.IMREAD_GRAYSCALE)
imagen_original = cv2.GaussianBlur(img, (9, 9), 0)
# Aplicar la detección de bordes con DWT y PSO
print("DWT CON PSO".center(50,'-'))
imagen_bordes_pso = edge_detection_with_dwt_pso(imagen_original)
#Funcion de obtencion de bordes con Sobel
def funcion_sobel(imagenEngris):
# Aplicar Sobel en ambas direcciones
sobelx = cv2.Sobel(imagenEngris, cv2.CV_64F, 1, 0, ksize=3) # Sobel en X
sobely = cv2.Sobel(imagenEngris, cv2.CV_64F, 0, 1, ksize=3) # Sobel en Y
# Calcular la magnitud del gradiente
magnitud = np.sqrt(sobelx**2 + sobely**2)
# Aplicar un umbral para definir los bordes
_, imagen_bordes = cv2.threshold(magnitud, 150, 255, cv2.THRESH_BINARY)
return imagen_bordes
imagen_bordes_sobel = funcion_sobel(imagen_original)
# Mostrar las imágenes
cv2.imshow('Imagen Original', imagen_original)
cv2.imshow('Bordes Detectados DWT-PSO', imagen_bordes_pso)
cv2.imshow('Bordes Detectados Con Sobel', imagen_bordes_sobel)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Guardar la imagen con los bordes detectados
cv2.imwrite('bordes_detectados_dwt_pso.png', imagen_bordes_pso)
cv2.imwrite('bordes_detectados_sobel.png', imagen_bordes_sobel)
#--- Metricas de calidad entre las imagenes ---
def mse(imageA, imageB):
# Asegúrate de que las imágenes tengan el mismo tamaño
assert imageA.shape == imageB.shape
# Calcula el error cuadrático medio (MSE)
err = np.sum((imageA - imageB) ** 2)
mse_value = err / float(imageA.shape[0] * imageA.shape[1])
return mse_value
def psnr(imageA, imageB):
mse_value = mse(imageA, imageB)
if mse_value == 0:
return float('inf') # Las imágenes son idénticas
max_pixel = 255.0 # Suponiendo imágenes de 8 bits
psnr_value = 20 * np.log10(max_pixel / np.sqrt(mse_value))
return psnr_value
#Se imprimen calidad de las imagenes
print("\n");
print("METRICAS DE CALIDAD ENTRE LAS IMAGENES".center(50,'-'))
#Metricas de calidad entre PSO y Original
print("PSNR entre DWT-PSO y Original: ", psnr(imagen_bordes_pso, imagen_original))
print("MSE entre DWT-PSO y Original: ", mse(imagen_bordes_pso, imagen_original))
#Metricas de calidad entre Sobel y Original
print("PSNR entre Sobel y Original: ", psnr(imagen_bordes_sobel, imagen_original))
print("MSE entre Sobel y Original: ", mse(imagen_bordes_sobel, imagen_original))