# Removing the edge features of an image while enhancing internal connectors

I picked up the following leaf today while going for a walk.

And wanted then to run the same analysis that @Vitaly Kaurov did for rivers under this posting

Measuring Fractal Dimensions of natural objects from digital images

and then also proceed to measure the length of branches and angles of the ribs and veins of the leaf as shown in this other posting.

how-to-measure-segment-length-and-branch-angle

The final objective would be to collect different leaves from different species and prepare some sort of visualization of the different species.

I played around with different ImageProcessing functions, the best I could do was the following.

leaf = ImageRotate[Import["http://i.stack.imgur.com/cnvC4.jpg"], \[Pi]/2];
leafBW = ColorSeparate[leaf, "RGB"][[3]];
ribs = ImageAdd[MinDetect[leafBW, 0.27], MaxDetect[leafBW, 0.27]]


The questions are:

1. Is there a better way to process the image to maximize the details of ribs and secondary veins?
2. How can we eliminate the edge of the leaf from the image?
-
Is this good enough? –  rm -rf Jul 27 '13 at 17:52
Looks great @rm-rf. Is there any way to remove the border of the leaf too? –  Zviovich Jul 27 '13 at 18:03
Hmmm... I'm not satisfied with the result. While it seems to capture a lot of the smaller cells, a good number of them are spurious, as you can see from the overlay image. Perhaps nikie/Matthias or others might have better suggestions (I used a RidgeFilter followed by Binarize and played with the thresholds). Yours is more accurate than mine. –  rm -rf Jul 27 '13 at 18:20
I noticed that the picture was a bit blurred in places. If you could press it between two sheets of glass it could provide more detail... –  cormullion Jul 27 '13 at 19:56
@cormullion Your comment is OT :) –  belisarius Jul 28 '13 at 2:47

I fiddled around a bit with the image you provided. First of all: image quality suffers greatly from (i) bad imaging conditions, especially image blur resulting from not pressing the leaf evenly onto the scanner, and (ii) the JPEG compression artifacts.

Initially we cut out the interesting part of the image

leaf = ImageTake[ImageRotate[Import["http://i.stack.imgur.com/cnvC4.jpg"], \[Pi]/2], {50,620}, {10, 1120}]


and convert it to grayscale

leafg = ColorConvert[leaf, "Grayscale"]


then we sharpen it to get more detail in the heavily blurred image areas (this is a sledge-hammer approach).

leafs = Sharpen[leafg, 20]


In order to get the mask for eliminating the edge of the leaf from the image we binarize the image, clear the image of small components and dilate the mask inwardly.

mask = Dilation[DeleteSmallComponents[Binarize[leafg], Method -> "Cluster"], 10]


Now we have a choice: are we interested in the major ribs and secondary veins (A) or do we want to get all possible veins (B).

(A): To get major ribs and secondary veins only we apply a ridge filter with a width of 3 pixels

rfp = ImageAdjust[RidgeFilter[leafs, 3]]


and binarize the resulting image.

rf = Binarize[rfp, FindThreshold[rfp, Method -> "Mean"]]


Then we skeletonize the segmentation

skelimg1 = Thinning[rf]


and remove the edge of the leaf using our generated mask.

res1 = ImageSubtract[skelimg1, mask]


This is the result of (A):

ImageAdd[leaf, res1]


(B): To get all veins we apply a ridge filter with a width of 1.5 pixels

rf1p = ImageAdjust[RidgeFilter[leafs, 1.5]]


and binarize the resulting image.

rf1 = Binarize[rf1p, FindThreshold[rf1p, Method -> "Mean"]]


As one can see there are some areas in the middle of the stem that were not segmented correctly. These artifacts are the result of the ridge filter operation: 1.5 pixels are suitable for the enhancement of fine veins but do not work for thick ribs. Thinning of this segmentation would produce loops on the stem. To counter this effect we generate a second segmentation with a ridge filter of width 3.5 (the threshold requires some manual adaption because of the bad image quality)

rf2 = Binarize[ImageAdjust[RidgeFilter[leafs, 3.5]], 0.17]


and add the two images. As we see, the blurred areas cannot be properly segmented.

ridgeimg = ImageAdd[rf1, rf2]


Then we skeletonize the segmentation

skelimg2 = Thinning[ridgeimg]


and remove the edge of the leaf using our generated mask.

res2 = ImageSubtract[skelimg2, mask]


This is the result of (B):

ImageAdd[leaf, res2]


For analysis you should remove all separate components to get the true connected skeleton. And, of course, please do optimize the imaging conditions ;).

-
+1 nice answer. Leaves nothing for anyone else to do... :) –  cormullion Dec 4 '13 at 10:17