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]


1on aBinarized image always supplies the filter function with zeroes. – Martin Ender Mar 21 '16 at 13:45img = Binarize@RandomImage[1, {10, 10}]; ImageFilter[(Print@#; 1) &, img, 1]– Martin Ender Mar 21 '16 at 13:5076 == 42 + 34as expected :) – Dr. belisarius Mar 21 '16 at 14:22ImageType(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?). – Martin Ender Mar 21 '16 at 14:30