fiensop / canny_edge_detector Goto Github PK
View Code? Open in Web Editor NEWCanny Edge detector library
Canny Edge detector library
The comparison of image pixel intensity should be in the direction of gradient or the one opposite to that direction. The q and r that are compared in the non_max_suppression function are the pixels in the perpendicular direction to this gradient. This is incorrect.
Hi @FienSoP,
Thank you for this useful guide for edge detection in 2D images.
I personally need this tool for a 3D image, so I tried to rewrite it with that in mind. I thought I was doing well, but the results from the non_maximum_suppression are not what I hoped for. Maybe you or someone else can assist me with this:
def sobel_filters(img):
Kx = np.array([[[1, 0, -1], [2, 0, -2], [1, 0, -1]],[[2, 0, -2], [4, 0, -4], [2, 0, -2]],[[1, 0, -1], [2, 0, -2], [1, 0, -1]]], np.float32)
Ky = np.array([[[1, 2, 1], [0, 0, 0], [-1, -2, -1]],[[2, 4, 2], [0, 0, 0], [-2, -4, -2]],[[1, 2, 1], [0, 0, 0], [-1, -2, -1]]], np.float32)
Kz = np.array([[[1, 2, 1], [2, 4, 2], [1, 2, 1]],[[0, 0, 0], [0, 0, 0], [0, 0, 0]],[[-1, -2, -1], [-2, -4, -2], [-1, -2, -1]]], np.float32)
Ix = ndimage.filters.convolve(img, Kx)
Iy = ndimage.filters.convolve(img, Ky)
Iz = ndimage.filters.convolve(img, Kz)
G = np.sqrt(Ix**2 + Iy**2 + Iz**2)
G = G / G.max() * 255
phi = np.arctan2(Iy,Ix)
theta = np.arctan2(Iy,Iz)
return (G,phi,theta)
Where phi and theta represent spherical coordinates.
This results in something I would more or less expect:
With those outcomes, I apply the non_max_suppression:
def non_max_suppression(img, phi, theta):
M, N, O = img.shape
Z = np.zeros((M,N,O), dtype=np.int32)
phi[phi < 0] += np.pi
theta[theta < 0] += np.pi
for i in range(1,M-1):
for j in range(1,N-1):
for k in range(1,O-1):
try:
q = 255
r = 255
#theta 0
if (0 <= theta[i,j,k] < (0.125*np.pi)) or ((0.875*np.pi) <= theta[i,j,k] <= np.pi):
q = img[i, j, k+1]
r = img[i, j, k-1]
#theta 1/4 pi
elif ((0.125*np.pi) <= theta[i,j,k] < (0.375*np.pi)):
#phi 0
if(0 <= phi[i,j,k] < (0.125*np.pi)) or ((0.875*np.pi) <= phi[i,j,k] <= np.pi):
q = img[i+1, j, k+1]
r = img[i-1, j, k-1]
#phi 1/4 pi
elif((0.125*np.pi) <= phi[i,j,k] < (0.375*np.pi)):
q = img[i+1, j+1, k+1]
r = img[i-1, j-1, k-1]
#phi 1/2 pi
elif((0.375*np.pi) <= phi[i,j,k] < (0.625*np.pi)):
q = img[i, j+1, k+1]
r = img[i, j-1, k-1]
#phi 3/4 pi
elif((0.625*np.pi) <= phi[i,j,k] < (0.875*np.pi)):
q = img[i-1, j+1, k+1]
r = img[i+1, j-1, k-1]
#theta 1/2 pi
elif ((0.375*np.pi) <= theta[i,j,k] < (0.625*np.pi)):
#phi 0
if(0 <= phi[i,j,k] < (0.125*np.pi)) or ((0.875*np.pi) <= phi[i,j,k] <= np.pi):
q = img[i+1, j, k]
r = img[i-1, j, k]
#phi 1/4 pi
elif((0.125*np.pi) <= phi[i,j,k] < (0.375*np.pi)):
q = img[i+1, j+1, k]
r = img[i-1, j-1, k]
#phi 1/2 pi
elif((0.375*np.pi) <= phi[i,j,k] < (0.625*np.pi)):
q = img[i, j+1, k]
r = img[i, j-1, k]
#phi 3/4 pi
elif((0.625*np.pi) <= phi[i,j,k] < (0.875*np.pi)):
q = img[i-1, j+1, k]
r = img[i+1, j-1, k]
#theta 3/4 pi
elif ((0.625*np.pi) <= theta[i,j,k] < (0.875*np.pi)):
#phi 0
if(0 <= phi[i,j,k] < (0.125*np.pi)) or ((0.875*np.pi) <= phi[i,j,k] <= np.pi):
q = img[i+1, j, k-1]
r = img[i-1, j, k+1]
#phi 1/4 pi
elif((0.125*np.pi) <= phi[i,j,k] < (0.375*np.pi)):
q = img[i+1, j+1, k-1]
r = img[i-1, j-1, k+1]
#phi 1/2 pi
elif((0.375*np.pi) <= phi[i,j,k] < (0.625*np.pi)):
q = img[i, j+1, k-1]
r = img[i, j-1, k+1]
#phi 3/4 pi
elif((0.625*np.pi) <= phi[i,j,k] < (0.875*np.pi)):
q = img[i-1, j+1, k-1]
r = img[i+1, j-1, k+1]
if (img[i,j,k] >= q) and (img[i,j,k] >= r):
Z[i,j,k] = img[i,j,k]
else:
Z[i,j,k] = 0
except IndexError as e:
pass
return Z
This, however, results in an array full of zeros for Z, which means nothing really happened.
Any tip is welcome!
UPDATE
It seemed that return
was shifted and because of the long code it was not easy to see.. Good news: easy fix, bad news: long time needed to find out this stupid mistake.
I'll keep you updated if I manage to have the 3D version completely working.
UPDATE 2.0
I think I made it work! You can find it on my Github page. .
Best,
Ilva
Hi! Thanks for your great work which helps a lot in finishing my homework. ๐
I just have one question about the implementation logic of the function 'hysteresis' in which weak edges need to be connected if they are an extension of some strong edge. The code below seems to leave some weak edges not handled as the order of processing pixels. For example if an image edge array looks like [weak, weak, strong]
, then the first weak pixel won't be connected to the strong pixel as it cannot pass the if condition sentence before the second weak pixel is changed to strong.
I'm not sure if I understand your code logic correctly so I just put it forward.
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.