"""
PROJETO INTEGRADOR: Detecção de Bordas com Transformações Lineares
------------------------------------------------------------------
Autor: [Seu Nome/Grupo]
Curso: Engenharia de Software - CEUB
Objetivos:
1. Implementar filtros de borda (Sobel, Laplace) via Convolução.
2. Demonstrar a Linearidade da operação (Álgebra Linear).
3. Comparar implementação manual vs. TensorFlow nativo.
4. Desafio: Kernel personalizado.
"""
import os
# Configuração de logs do TensorFlow para evitar poluição visual
[Link]['TF_CPP_MIN_LOG_LEVEL'] = '3'
import numpy as np
import [Link] as plt
# Tenta importar TensorFlow
use_tf = False
try:
import tensorflow as tf
tf.get_logger().setLevel("ERROR")
use_tf = True
print(f"TensorFlow versão {tf.__version__} carregado com sucesso.")
except ImportError:
from [Link] import convolve2d
print("AVISO: TensorFlow não encontrado. Algumas funcionalidades (comparação
nativa) serão desativadas.")
# -----------------------------------------------------------------
# 1. Definição dos Kernels (Matrizes de Transformação)
# -----------------------------------------------------------------
# Sobel X: Gradiente na direção horizontal (detecta linhas verticais)
SOBEL_X = [Link]([
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
], dtype=np.float32)
# Sobel Y: Gradiente na direção vertical (detecta linhas horizontais)
SOBEL_Y = [Link]([
[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]
], dtype=np.float32)
# Laplaciano: Derivada de segunda ordem (detecta mudanças bruscas em qualquer
direção)
LAPLACE = [Link]([
[0, 1, 0],
[1, -4, 1],
[0, 1, 0]
], dtype=np.float32)
# Kernel Personalizado (Desafio): Sharpening / Realce de Bordas
# Aumenta o contraste entre pixels adjacentes
CUSTOM_KERNEL = [Link]([
[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]
], dtype=np.float32)
# -----------------------------------------------------------------
# 2. Funções de Processamento e Matemática
# -----------------------------------------------------------------
def create_test_image(size=128):
"""Gera uma imagem sintética geométrica para facilitar a visualização das
bordas."""
img = [Link]((size, size), dtype=np.float32)
# Quadrado central
s = size // 4
img[s:3*s, s:3*s] = 0.6
# Círculo
cy, cx = size // 2, size // 2
Y, X = [Link][:size, :size]
mask = (X - cx)**2 + (Y - cy)**2 < (size // 6)**2
img[mask] = 1.0
return img
def apply_conv(image, kernel):
"""
Aplica a convolução 2D.
Matematicamente: (f * g)[n] = soma(f[m] * g[n-m])
"""
if use_tf:
# Prepara tensores: [Batch, Height, Width, Channels]
image_tensor = [Link](image[[Link], :, :, [Link]])
kernel_tensor = [Link](kernel[:, :, [Link], [Link]])
# Operação de Convolução (Linear)
result = [Link].conv2d(
input=image_tensor,
filters=kernel_tensor,
strides=1,
padding='SAME'
)
return [Link]()[0, :, :, 0]
else:
return convolve2d(image, kernel, mode='same', boundary='symm')
def check_linearity(kernel, size=64):
"""
PROVA DE CONCEITO: Verifica se a Convolução é uma Transformação Linear.
Teoria: T(a*u + b*v) = a*T(u) + b*T(v)
"""
print("\n--- 1. Teste de Linearidade (Álgebra Linear) ---")
if not use_tf:
print("Requer TensorFlow para precisão.")
return
# Gera duas imagens aleatórias (vetores u e v)
u = [Link](size, size).astype(np.float32)
v = [Link](size, size).astype(np.float32)
# Escalares (a e b)
a, b = 0.5, 2.0
# Lado Esquerdo da equação: T(a*u + b*v)
linear_combination_input = a * u + b * v
left_side = apply_conv(linear_combination_input, kernel)
# Lado Direito da equação: a*T(u) + b*T(v)
right_side = a * apply_conv(u, kernel) + b * apply_conv(v, kernel)
# Verifica a diferença (Erro)
diff = [Link]([Link](left_side - right_side))
print(f"Erro máximo encontrado: {diff:.10f}")
if diff < 1e-5:
print(">> RESULTADO: A operação é LINEAR (comprovado).")
else:
print(">> RESULTADO: A operação NÃO é linear.")
def compare_native_sobel(image):
"""
Compara a implementação manual do kernel Sobel com a função nativa do
TensorFlow.
Requisito do projeto para validação.
"""
print("\n--- 2. Comparação com TensorFlow Nativo ---")
if not use_tf: return
# Implementação Manual
manual_sobel_x = apply_conv(image, SOBEL_X)
# Implementação Nativa ([Link].sobel_edges)
img_tensor = [Link](image[[Link], :, :, [Link]])
sobel_native = [Link].sobel_edges(img_tensor)
# O TF retorna [Batch, H, W, Channels, 2] (última dimensão: 0=y, 1=x)
# Nota: O TF define Y como vertical (0) e X como horizontal (1)
tf_sobel_x = sobel_native[0, :, :, 0, 1].numpy() # Canal X
# Visualização da comparação
fig, ax = [Link](1, 3, figsize=(15, 4))
ax[0].imshow(manual_sobel_x, cmap='gray')
ax[0].set_title("Nossa Implementação (Kernel)")
ax[1].imshow(tf_sobel_x, cmap='gray')
ax[1].set_title("[Link].sobel_edges")
# Diferença
diff = [Link](manual_sobel_x - tf_sobel_x)
ax[2].imshow(diff, cmap='viridis')
ax[2].set_title(f"Diferença (Erro Máx: {[Link]():.2f})")
plt.tight_layout()
[Link]()
print("Comparação visual gerada acima.")
# -----------------------------------------------------------------
# 3. Execução Principal
# -----------------------------------------------------------------
if __name__ == "__main__":
# A. Preparação
img = create_test_image()
# B. Teste Teórico (Linearidade)
check_linearity(SOBEL_X)
# C. Comparação Técnica (TensorFlow Nativo)
compare_native_sobel(img)
# D. Aplicação dos Filtros e Visualização Final
print("\n--- 3. Visualização dos Filtros Aplicados ---")
gx = apply_conv(img, SOBEL_X)
gy = apply_conv(img, SOBEL_Y)
gmag = [Link](gx**2 + gy**2) # Magnitude do gradiente (Hipotenusa)
lap = apply_conv(img, LAPLACE)
custom = apply_conv(img, CUSTOM_KERNEL)
# Plotagem
fig, ax = [Link](2, 3, figsize=(16, 10))
ax = [Link]()
kernels_results = [
(img, "Original"),
(gx, "Sobel X (Bordas Verticais)"),
(gy, "Sobel Y (Bordas Horizontais)"),
(gmag, "Magnitude (Todas as direções)"),
(lap, "Laplaciano (Segunda Derivada)"),
(custom, "Desafio: Kernel Personalizado (Sharpen)")
]
for i, (data, title) in enumerate(kernels_results):
ax[i].imshow(data, cmap="gray")
ax[i].set_title(title, fontsize=12, fontweight='bold')
ax[i].axis("off")
[Link]("Projeto Integrador: Análise de Filtros Convolucionais",
fontsize=16)
plt.tight_layout()
[Link]()