First I only take the part of the image where the majority of the defects reside:
bubblyPart = ImageTake[img, {90, All}, {375, 500}]
bubblyPixels = ImageData[bubblyPart];
Then I only look at the 2nd channel of the RGB values. This appeared to work best for finding the defects (the third channel works very well for some defects, but not all):
channel2 = Image[bubblyPixels[[All, All, 2]]]
I then apply your exact method in your question to highlight the defects (I just changed some of the selection criteria in SelectComponents
) and this appears to work sufficiently well:
lf = LaplacianGaussianFilter[channel2, 1];
laf = LocalAdaptiveBinarize[lf, 5, {1, 0, 0.04}];
mc = MorphologicalComponents[laf, CornerNeighbors -> False] //
Colorize;
SelectComponents[mc, {"Area", "Count",
"Elongation"}, #1 > 0 && #2 > 12 && #3 < 0.7 &]
This does miss some of the smaller defects, but you may able to mess with the parameters in LocalAdaptiveBinarize
and SelectComponents
components to get better defect detection. It is also highlighting the edge in the bottom right of the image, but you can just remove the defects highlighted on the bottom right of the image since it looks like the defects are always either on the top or left side of this part of the image.
If it's not always going to be true that the defects are on the left or top for all cases, this will be a little tougher, but you can increase the minimum allowed "Count"
to remove the bottom right edge at the expense of missing some smaller defects:
lf = LaplacianGaussianFilter[channel2, 1];
laf = LocalAdaptiveBinarize[lf, 5, {1, 0, 0.04}];
mc = MorphologicalComponents[laf, CornerNeighbors -> False] //
Colorize;
SelectComponents[mc, {"Area", "Count",
"Elongation"}, #1 > 0 && #2 > 19 && #3 < 0.7 &]
Add-on: I really need to work on my reading comprehension skills it seems. I see you said in the question you only want to reliably find the 3 largest defects. We can Increase the minimum "Count" req in SelectComponents
and apply this to the second channel of the image to easily get the 3 largest defects:
img2 = ColorSeparate[img][[2]];
lf = LaplacianGaussianFilter[img2, 1];
laf = LocalAdaptiveBinarize[lf, 5, {1, 0, 0.04}];
mc = MorphologicalComponents[laf, CornerNeighbors -> False] //
Colorize;
sc = SelectComponents[
mc, {"Area", "Count",
"Elongation"}, #1 > 10 && #2 > 50 && #3 < 0.7 &];
sc = RemoveBackground[sc // Binarize];
ImageCompose[img, sc]
You will have to check with other examples to make sure #2 > 50
in SelectComponents
works in general however.
Another add-on
If you are imaging something very regular (like the T shaped thing in the background is always the same) you could take an image of that with no defects to develop a template that we could ImageSubtract
from the image with defects; this could improve defect detection.
Closing
? $\endgroup$