% --- Selección de imagen desde el buscador ---
[archivo, ruta] = uigetfile({'*.jpg;*.png;*.bmp'}, 'Selecciona una imagen');
if isequal(archivo,0)
disp('No se seleccionó ninguna imagen');
return
end
i = imread(fullfile(ruta, archivo));
% --- Conversión a escala de grises (fórmula manual) ---
if size(i,3) == 3
R = double(i(:,:,1));
G = double(i(:,:,2));
B = double(i(:,:,3));
i = 0.2989 * R + 0.5870 * G + 0.1140 * B; % fórmula NTSC
else
i = double(i);
end
% --- Crear máscaras Gaussianas a mano ---
tam = 5; % tamaño kernel
s1 = 1; % sigma1
s2 = 2; % sigma2
r = floor(tam/2);
[x, y] = meshgrid(-r:r, -r:r);
G1 = exp(-(x.^2 + y.^2)/(2*s1^2));
G1 = G1 / sum(G1(:));
G2 = exp(-(x.^2 + y.^2)/(2*s2^2));
G2 = G2 / sum(G2(:));
% --- Expandir imagen manualmente ---
[fil, col] = size(i);
img_expand = zeros(fil + 2*r, col + 2*r);
img_expand(1+r:end-r, 1+r:end-r) = i;
% --- Convolución manual con G1 ---
conv1 = zeros(fil, col);
for a = 1:fil
for b = 1:col
reg = img_expand(a:a+2*r, b:b+2*r);
conv1(a,b) = sum(sum(reg .* G1));
end
end
% --- Convolución manual con G2 ---
conv2 = zeros(fil, col);
for a = 1:fil
for b = 1:col
reg = img_expand(a:a+2*r, b:b+2*r);
conv2(a,b) = sum(sum(reg .* G2));
end
end
% --- Diferencia de Gaussianas (DoG) ---
DoG = conv2 - conv1;
% --- Normalización manual ---
DoG_min = min(DoG(:));
DoG_max = max(DoG(:));
DoG_norm = (DoG - DoG_min) / (DoG_max - DoG_min);
% --- Binarización manual por umbral ---
umbral = mean(DoG_norm(:));
binaria = zeros(fil, col);
for a = 1:fil
for b = 1:col
if DoG_norm(a,b) > umbral
binaria(a,b) = 255;
else
binaria(a,b) = 0;
end
end
end
% --- Transformada de Hough manual básica ---
theta = -90:1:89; % grados
rho_max = ceil(sqrt(fil^2 + col^2));
rhos = -rho_max:1:rho_max;
acum = zeros(length(rhos), length(theta));
% Binarizar imagen lógica
for x = 1:fil
for y = 1:col
if binaria(x,y) == 255
for ang = 1:length(theta)
t = deg2rad(theta(ang));
rho = round(x*cos(t) + y*sin(t));
idx_rho = rho + rho_max + 1;
acum(idx_rho, ang) = acum(idx_rho, ang) + 1;
end
end
end
end
% --- Detección de picos manual (valor umbral alto) ---
umbral_hough = max(acum(:)) * 0.5;
[rr, cc] = find(acum > umbral_hough);
% --- Mostrar resultados ---
figure('Name','Resultado Completo','NumberTitle','off')
subplot(2,2,1)
imshow(uint8(i))
title('Imagen en escala de grises')
subplot(2,2,2)
imshow(uint8(binaria))
title('Imagen Binarizada (DoG)')
subplot(2,2,3)
imshow(imadjust(rescale(acum)),[],...
'XData',theta,'YData',rhos)
xlabel('\theta'), ylabel('\rho')
axis on, axis normal
colormap(gca, hot)
title('Espacio de Hough')
% --- Dibujo de líneas detectadas ---
subplot(2,2,4)
imshow(uint8(i))
title('Líneas detectadas (Hough)')
hold on
for k = 1:length(rr)
rho = rhos(rr(k));
t = deg2rad(theta(cc(k)));
% Si la línea no es vertical
if abs(sin(t)) > 1e-4
x1 = 1;
y1 = (rho - x1*cos(t))/sin(t);
x2 = col;
y2 = (rho - x2*cos(t))/sin(t);
% Solo dibuja si los puntos están dentro del rango visible
if y1 >= 1 && y1 <= fil && y2 >= 1 && y2 <= fil
plot([x1 x2], [y1 y2], 'g', 'LineWidth', 1.5)
end
else
% Línea casi vertical
y1 = 1;
y2 = fil;
x = round(rho / cos(t));
if x >= 1 && x <= col
plot([x x], [y1 y2], 'g', 'LineWidth', 1.5)
end
end
end