# How to extract graph from microscope image?

I have a microscope image of actin filaments and I'd like to extract the geometry of the bright lines into a Graph object:

Here's what I have so far, using the above image as img:

s1 = MaxDetect@
s2 = MaxDetect[s1];
s3 = TopHatTransform[s2, 0.74];
s4 = DeleteSmallComponents[s2 - s3];
HighlightImage[img, s4]


But this misses lots of lines and the output isn't really a skeleton.

Here are a few more example images of the cytoskeleton to try this on:

example1 = CloudGet["https://www.wolframcloud.com/objects/defc77bb-8218-4660-9fb2-d851c1145cae"]
example2 = CloudGet["https://www.wolframcloud.com/objects/b44045ec-f7ce-4db0-82bf-57e86d1967ac"]

• Hm. Maybe you want to give MorphologicalGraph[s1] a try... But I am afraid, that is not exactly what you look for. – Henrik Schumacher Jul 22 '18 at 22:29
• That's the first thing I tried, but the preprocessing is the tricky part – M.R. Jul 22 '18 at 22:31
• Yeah, I guess so. – Henrik Schumacher Jul 22 '18 at 23:00
• Not a MMA answer, but for preprocessing I'd check out iLastik. After performing the segmentation with that, you could easily use mathematica for further processing. – yohbs Jul 23 '18 at 20:38

Sorry for being late at the party, I hope it is still relevant. This is what I would do:

Setting your image as img I first equalize the brightness with BrightnessEqualize, then Sharpen the image, followed by some slight Blur, Erosion and a RidgeFilter that should bring us quite close to where you want to go

beq = BrightnessEqualize[img, {"Marginal", 2}]


sh = Sharpen[beq, 10]
bl = Blur[sh, 1];
er = Erosion[bl, 1];
rid = RidgeFilter[er, 2] // ImageAdjust;


Finally a LocalAdaptiveBinarize and a Thinning will give you what I hope is what you are looking for

lab = LocalAdaptiveBinarize[rid, 1]


Thinning[lab]


Optional:

If the First Local Adaptive Binarization step is giving you lines that are too thick, but the thinning backbone is too thin for what you need, you can perform a couple more Local Abdaptive Binarization followed by by blur, erosion, ridge filtering, sharpening... etc to get thinner lines

bin2 = ImageAdjust[lab~Blur~1~RidgeFilter~1] // Sharpen // Binarize


bin3 = ImageAdjust[bin2~Blur~2~Erosion~1~RidgeFilter~1] // Sharpen //


Binarize

Finally you can also create a Vectorized version of all your results using ImageGraphics

I Hope it helps.

• I'm working on a related problem and I wasn't aware of either BrightnessEqualize or RidgeFilter. Very useful, +1! (I interfaced with SimpleITK through LibraryLink/LTemplate to get a local histogram equalization instead.) – Szabolcs Aug 27 '18 at 10:54
• This answer is much better than my comment masquerading as an answer. I agree with @Szabolcs that there are a few functions in here that are very useful -- and previously unknown, at least to me. – Kellen Myers Apr 18 at 21:20

This is too big for a comment, but I wouldn't consider it an answer, more of a suggestion or partial answer. I don't have any solid expertise in this area, but it seems to me like if you want to highlight these lines, you might want to do some edge detection. For example:

s1 = LocalAdaptiveBinarize[
EdgeDetect[img, 2, 0.0275, Method -> "Sobel"],
100, PerformanceGoal -> "Quality"
];
HighlightImage[img, s1]


I'm not sure what it is we want to see, but to my eye this might be a step in the right direction at least. (?)

Also, I don't want to be "that guy," but are there higher resolution versions of these images? I might be wrong because this isn't exactly my wheelhouse, but I get the feeling it might be partially attributable to the fuzziness of the image, everything sort of glows and blends in, which might be less of an issue in a higher resolution image.