Spaces:
Runtime error
Runtime error
import gradio as gr | |
import cv2 | |
import matplotlib.pyplot as plt | |
from scipy import ndimage | |
from scipy.ndimage.filters import convolve | |
import numpy as np | |
def hysteresis(img, weak = 75, strong=255): | |
M, N = img.shape | |
for i in range(1, M-1): | |
for j in range(1, N-1): | |
if (img[i,j] == weak): | |
try: | |
if ((img[i+1, j-1] == strong) or (img[i+1, j] == strong) or (img[i+1, j+1] == strong) | |
or (img[i, j-1] == strong) or (img[i, j+1] == strong) | |
or (img[i-1, j-1] == strong) or (img[i-1, j] == strong) or (img[i-1, j+1] == strong)): | |
img[i, j] = strong | |
else: | |
img[i, j] = 0 | |
except IndexError as e: | |
pass | |
return img | |
def threshold(img, lowThresholdRatio=0.05, highThresholdRatio=0.09): | |
highThreshold = img.max() * highThresholdRatio; | |
lowThreshold = highThreshold * lowThresholdRatio; | |
M, N = img.shape | |
res = np.zeros((M,N), dtype=np.int32) | |
weak = np.int32(25) | |
strong = np.int32(255) | |
strong_i, strong_j = np.where(img >= highThreshold) | |
zeros_i, zeros_j = np.where(img < lowThreshold) | |
weak_i, weak_j = np.where((img <= highThreshold) & (img >= lowThreshold)) | |
res[strong_i, strong_j] = strong | |
res[weak_i, weak_j] = weak | |
return (res) | |
def non_max_suppression(img, D): | |
M, N = img.shape | |
Z = np.zeros((M,N), dtype=np.int32) | |
angle = D * 180. / np.pi | |
angle[angle < 0] += 180 | |
for i in range(1,M-1): | |
for j in range(1,N-1): | |
try: | |
q = 255 | |
r = 255 | |
#angle 0 | |
if (0 <= angle[i,j] < 22.5) or (157.5 <= angle[i,j] <= 180): | |
q = img[i, j+1] | |
r = img[i, j-1] | |
#angle 45 | |
elif (22.5 <= angle[i,j] < 67.5): | |
q = img[i+1, j-1] | |
r = img[i-1, j+1] | |
#angle 90 | |
elif (67.5 <= angle[i,j] < 112.5): | |
q = img[i+1, j] | |
r = img[i-1, j] | |
#angle 135 | |
elif (112.5 <= angle[i,j] < 157.5): | |
q = img[i-1, j-1] | |
r = img[i+1, j+1] | |
if (img[i,j] >= q) and (img[i,j] >= r): | |
Z[i,j] = img[i,j] | |
else: | |
Z[i,j] = 0 | |
except IndexError as e: | |
pass | |
return Z | |
def gaussian_kernel(size, sigma=1): | |
size = int(size) // 2 | |
x, y = np.mgrid[-size:size+1, -size:size+1] | |
normal = 1 / (2.0 * np.pi * sigma**2) | |
g = np.exp(-((x**2 + y**2) / (2.0*sigma**2))) * normal | |
return g | |
def sobel_filters(img): | |
Kx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], np.float32) | |
Ky = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]], np.float32) | |
Ix = ndimage.filters.convolve(img, Kx) | |
Iy = ndimage.filters.convolve(img, Ky) | |
G = np.hypot(Ix, Iy) | |
G = G / G.max() * 255 | |
theta = np.arctan2(Iy, Ix) | |
return (G, theta) | |
def canny(img, kernel, sigma): | |
img_color = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | |
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
img_gaussian = convolve(img_gray, gaussian_kernel(kernel, sigma)) | |
G, theta = sobel_filters(img_gaussian) | |
img_nonmax = non_max_suppression(G, theta) | |
img_threshold = threshold(img_nonmax) | |
img_final = hysteresis(img_threshold) | |
return img_final | |
interface = gr.Interface( | |
title = "Canny Edge Detector π€", | |
description = "<h3>The Canny edge detector is an edge detection operator that uses a multi-stage algorithm to detect a wide range of edges in images.</h3> <br> <b>Select an image πΌ</b>", | |
article='Step-by-step on GitHub <a href="https://github.com/Ivanrs297/machine-learning-projects/blob/main/computer-vision/edge_detection/main.ipynb"> notebook </a> <br> ~ Ivanrs', | |
allow_flagging = "never", | |
fn = canny, | |
inputs = [ | |
gr.Image(), | |
gr.Slider(1, 9, step = 1, value=3, label = "Kernel Size"), | |
gr.Slider(1, 20, step = 5, value=10, label = "Sigma"), | |
], | |
outputs = "image" | |
) | |
interface.launch(share = False) |