Canny edge detector: Difference between revisions
Content added Content deleted
No edit summary |
|||
Line 834: | Line 834: | ||
There is a built-in function, [http://www.mathworks.com/help/images/ref/edge.html edge], that has Canny Edge Detection as one of its options. |
There is a built-in function, [http://www.mathworks.com/help/images/ref/edge.html edge], that has Canny Edge Detection as one of its options. |
||
<lang MATLAB>BWImage = edge(GrayscaleImage,'canny');</lang> |
<lang MATLAB>BWImage = edge(GrayscaleImage,'canny');</lang> |
||
=={{Header|Python}}== |
|||
In Python, canny edge detection would normally be done using [http://scikit-image.org/docs/dev/auto_examples/plot_canny.html scikit-image] or OpenCV-Python. Here is an approach using numpy/scipy: |
|||
<lang python>#!/bin/python |
|||
import numpy as np |
|||
from scipy.ndimage.filters import convolve, gaussian_filter |
|||
from scipy.misc import imread, imshow |
|||
def CannyEdgeDetector(im, blur = 1, highThreshold = 91, lowThreshold = 31): |
|||
im = np.array(im, dtype=float) #Convert to float to prevent clipping values |
|||
#Gaussian blur to reduce noise |
|||
im2 = gaussian_filter(im, 1) |
|||
#Use sobel filters to get horizontal and vertical gradients |
|||
im3h = convolve(im2,[[-1,0,1],[-2,0,2],[-1,0,1]]) |
|||
im3v = convolve(im2,[[1,2,1],[0,0,0],[-1,-2,-1]]) |
|||
#Get gradient and direction |
|||
grad = np.power(np.power(im3h, 2.0) + np.power(im3v, 2.0), 0.5) |
|||
theta = np.arctan2(im3v, im3h) |
|||
thetaQ = (np.round(theta * (5.0 / np.pi)) + 5) % 5 #Quantize direction |
|||
#Non-maximum suppression |
|||
gradSup = grad.copy() |
|||
for r in range(im.shape[0]): |
|||
for c in range(im.shape[1]): |
|||
#Suppress pixels at the image edge |
|||
if r == 0 or r == im.shape[0]-1 or c == 0 or c == im.shape[1] - 1: |
|||
gradSup[r, c] = 0 |
|||
continue |
|||
tq = thetaQ[r, c] % 4 |
|||
if tq == 0: #0 is E-W (horizontal) |
|||
if grad[r, c] <= grad[r, c-1] or grad[r, c] <= grad[r, c+1]: |
|||
gradSup[r, c] = 0 |
|||
if tq == 1: #1 is NE-SW |
|||
if grad[r, c] <= grad[r-1, c+1] or grad[r, c] <= grad[r+1, c-1]: |
|||
gradSup[r, c] = 0 |
|||
if tq == 2: #2 is N-S (vertical) |
|||
if grad[r, c] <= grad[r-1, c] or grad[r, c] <= grad[r+1, c]: |
|||
gradSup[r, c] = 0 |
|||
if tq == 3: #3 is NW-SE |
|||
if grad[r, c] <= grad[r-1, c-1] or grad[r, c] <= grad[r+1, c+1]: |
|||
gradSup[r, c] = 0 |
|||
#Double threshold |
|||
strongEdges = (gradSup > highThreshold) |
|||
#Strong has value 2, weak has value 1 |
|||
thresholdedEdges = np.array(strongEdges, dtype=np.uint8) + (gradSup > lowThreshold) |
|||
#Tracing edges with hysteresis |
|||
#Find weak edge pixels near strong edge pixels |
|||
finalEdges = strongEdges.copy() |
|||
currentPixels = [] |
|||
for r in range(1, im.shape[0]-1): |
|||
for c in range(1, im.shape[1]-1): |
|||
if thresholdedEdges[r, c] != 1: |
|||
continue #Not a weak pixel |
|||
#Get 3x3 patch |
|||
localPatch = thresholdedEdges[r-1:r+2,c-1:c+2] |
|||
patchMax = localPatch.max() |
|||
if patchMax == 2: |
|||
currentPixels.append((r, c)) |
|||
finalEdges[r, c] = 1 |
|||
#Extend strong edges based on current pixels |
|||
while len(currentPixels) > 0: |
|||
newPix = [] |
|||
for r, c in currentPixels: |
|||
for dr in range(-1, 2): |
|||
for dc in range(-1, 2): |
|||
if dr == 0 and dc == 0: continue |
|||
r2 = r+dr |
|||
c2 = c+dc |
|||
if thresholdedEdges[r2, c2] == 1 and finalEdges[r2, c2] == 0: |
|||
#Copy this weak pixel to final result |
|||
newPix.append((r2, c2)) |
|||
finalEdges[r2, c2] = 1 |
|||
currentPixels = newPix |
|||
return finalEdges |
|||
if __name__=="__main__": |
|||
im = imread("test.jpg", mode="L") #Open image, convert to greyscale |
|||
finalEdges = CannyEdgeDetector(im) |
|||
imshow(finalEdges)</python> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |