Canny edge detector: Difference between revisions
Content added Content deleted
Line 677: | Line 677: | ||
Edge and non-edge points are represented as zeros and ones respectively. Edges are sets of connected points. Edge points are considered to be connected if within a 3X3 region (or if they are connected to a common third edge point). Edges are represented as points having a common unique identifier. |
Edge and non-edge points are represented as zeros and ones respectively. Edges are sets of connected points. Edge points are considered to be connected if within a 3X3 region (or if they are connected to a common third edge point). Edges are represented as points having a common unique identifier. |
||
<lang J> |
<lang J> |
||
... implementation goes here ... |
|||
NB. 2D convolution, filtering, ... |
|||
convolve =: 4 : 'x apply (($x) partition y)' |
|||
partition =: 4 : '2 0 3 1 |: ((1{x) ([+\]) (2 0 1|: ((0{x) ([+\]) y)))' |
|||
apply =: 4 : '+/"1 (+/"2 (x *"2 y))' |
|||
addborder =: (0&,@|:@|.)^:4 |
|||
normalize =: ]%+/@, |
|||
resample =: 4 : '|: (1{-x)(+/%#)\ |: (0{-x)(+/%#)\ y' |
|||
crop =: 4 : 0 |
|||
'h w h0 w0' =: x |
|||
|: w{. w0}. |: h{. h0}. y |
|||
) |
|||
max3x3 =: 3 : '(1{1{y>0) * (>./,y)'"2 |
|||
attach =: 3 : 'max3x3 (3 3 partition (addborder y))' |
|||
unique =: 3 : 'y*i.$y' |
|||
connect =: 4 : 'attach^:x unique y' |
|||
canny =: 3 : 0 |
|||
image0 =: y |
|||
NB. Step 1 - gaussian smoothing |
|||
NB. Gaussian kernel (from Wikipedia article) |
|||
<] gaussianKernel =. 5 5$2 4 5 4 2 4 9 12 9 4 5 12 15 12 5 4 9 12 9 4 2 4 5 4 2 |
|||
gaussianKernel =. gaussianKernel % 159 |
|||
image1 =: gaussianKernel convolve image0 |
|||
NB. Step 2 - gradient |
|||
<] gradientKernel =. 3 3$0 _1 0 0j_1 0 0j1 0 1 0 |
|||
image2 =: gradientKernel convolve image1 |
|||
NB. Step 3 - edge detection |
|||
NB. find the octant (eighth of circle) in which the gradient lies |
|||
octant =: 3 : '4|(>.(_0.5+((4%(o. 1))*(12&o. y))))' |
|||
<(i:6)(4 : 'octant (x j. y)')"0/(i:6) |
|||
NB. is this gradient greater than [the projection of] a neighbor? |
|||
greaterThan =: 4 : ' (9 o.((x|.y)%y))<1' |
|||
NB. is this gradient the greatest of immmediate colinear neighbore? |
|||
greatestOf =: 4 : '(x greaterThan y) *. ((-x) greaterThan y)' |
|||
NB. relative address of neighbor relevant to grad direction |
|||
krnl0 =: _1 0 |
|||
krnl1 =: _1 _1 |
|||
krnl2 =: 0 _1 |
|||
krnl3 =: 1 _1 |
|||
og =: octant image2 |
|||
NB. mask for maximum gradient colinear with gradient |
|||
ok0 =: (0=og) *. krnl0 greatestOf image2 |
|||
ok1 =: (1=og) *. krnl1 greatestOf image2 |
|||
ok2 =: (2=og) *. krnl2 greatestOf image2 |
|||
ok3 =: (3=og) *. krnl3 greatestOf image2 |
|||
image3 =: image2 *. (ok0 +. ok1 +. ok2 +. ok3) |
|||
NB. Step 4 - Weak edge suppression |
|||
NB. weak, strong threshholds |
|||
NB. TODO: parameter picker algorithm or helper |
|||
threshholds =: 1e14 1e15 |
|||
nearbyKernel =: 3 3 $ 4 1 4 # 1 0 1 |
|||
magnitude =. 10&o. image3 |
|||
weak =: magnitude > 0{threshholds |
|||
strong =: magnitude > 1{threshholds |
|||
strongs =: addborder (nearbyKernel convolve strong) > 0 |
|||
image4 =: strong +. (weak *. strongs) |
|||
) |
|||
}</lang> |
}</lang> |
||
The above implementation solves the 'inner problem' of Canny Edge Detection fully in the J language, with no external dependencies. Standard libraries provide necessary additional support including interfaces to image file formats and graphic displays. |
The above implementation solves the 'inner problem' of Canny Edge Detection fully in the J language, with no external dependencies. Standard libraries provide necessary additional support including interfaces to image file formats and graphic displays. |
||
Line 683: | Line 754: | ||
<lang J> |
<lang J> |
||
1!:44'D:/rosettacode/canny' |
|||
... usage goes here … |
|||
load'canny.ijs' |
|||
NB. viewers |
|||
require'viewmat plot' |
|||
view =: (16b010101*i.256)&viewmat |
|||
splot =: 'surface;mesh 0'&plot |
|||
NB. image file importers/exporters |
|||
require'png jpeg bmp' |
|||
NB. image =: readjpeg 'camille.jpg' |
|||
NB. image =: readbmp 'chess.bmp' |
|||
NB. image =: readpng 'boat1.png' |
|||
NB. image =: readpng 'valve.png' |
|||
NB. image =: readjpeg 'lena.jpg' |
|||
NB. from http://people.sc.fsu.edu/~jburkardt/data/pgmb/pgmb.html, |
|||
NB> distributed under the GNU LGPL license. |
|||
image =: readpng 'bird.png' |
|||
NB. select (or combine) from color channels |
|||
NB. if original image is grayscale, take any color channel |
|||
red =: <. image % 65538 |
|||
green =: 256 | <. image % 256 |
|||
blue =: 256 | image |
|||
image =: blue |
|||
NB. detect the edges |
|||
edges =: canny image |
|||
view 1-edges |
|||
viewmat 1000 connect edges |
|||
</lang> |
</lang> |
||