Bug introduced in 9.0 and persisting through 13.1.0 [CASE:3968469]
When thinking on a way to answer this question using ImageFilter
I have found (with Jason B's help) that we can find the end points of the skeleton by increasing the radius in ImageFilter
from 1
to 2
in the following way:
pic = Thinning@Binarize@Import["https://i.stack.imgur.com/K8dm3.png"];
ep2 = ImageFilter[If[#[[3, 3]] == 1 && Total[#, 2] == 3, 1, 0] &, pic, 2];
ppos = PixelValuePositions[ep2, White]
{{271, 546}, {190, 471}, {694, 382}, {899, 366}}
But I cannot figure out why the original approach with radius 1
fails:
ep1 = ImageFilter[If[#[[2, 2]] == 1 && Total[#, 2] == 2, 1, 0] &, pic, 1];
PixelValuePositions[ep1, White]
{}
This looks unexpected because there is no actual difference between these two approaches as can be clearly seen by visualizing the neighborhood pixels in the thinned image:
ArrayPlot[1 - ImageData[ImageTrim[pic, {# - .5}, 2]], Mesh -> True,
ImageSize -> 100] & /@ ppos
Can anyone explain this issue? Is it a bug?
UPDATE: Additional observations
With the help by Martin Büttner I have discovered that in this particular case the filter function is always supplied with zeros when the radius is 1
. Even weirder, there are only 76 (!) evaluations of the filter function:
n = 0; count = 0;
ImageFilter[If[Total[#, 2] == 0, ++n; 0, ++n; ++count; 1] &, pic, 1];
{n, count}
{76, 0}
All the above output was obtained with version 10.4. With version 8.0.4 ImageFilter
behaves as expected:
pic = Thinning@Binarize@Import["https://i.stack.imgur.com/K8dm3.png"];
ep1 = ImageFilter[If[#[[2, 2]] == 1 && Total[#, 2] == 2, 1, 0] &, pic, 1];
Total[ImageData[ep1], 2]
4
So this seems to be a regression bug.
Reported as [CASE:3968469]
1
on aBinarize
d image always supplies the filter function with zeroes. $\endgroup$img = Binarize@RandomImage[1, {10, 10}]; ImageFilter[(Print@#; 1) &, img, 1]
$\endgroup$76 == 42 + 34
as expected :) $\endgroup$ImageType
(Bit
), it's possible to work around the issue by "unbinarising" the image withImage@N@ImageData@...
(although I wonder if there isn't a simpler way to convert image types?). $\endgroup$