## How to find the "true" perimeter of objects in a binary image?

### Xen (view profile)

on 11 Oct 2015
Latest activity Commented on by Xen

on 13 Oct 2015

### David Young (view profile)

Say, there is an object consisting of 3 pixels next to each other (■■■). If I calculate the perimeter using
sum(sum(bwperim(image)))
I get 3. But the actual perimeter (considering all sides of the object) is 8. How do I find this? Thanks.

Show 1 older comment
Xen

### Xen (view profile)

on 12 Oct 2015
Well, I see only one definition that gives a perimeter of 8 for those connected 3 pixels, which is not consistent with a perimeter of 2 or 4 or 0 or 58.3! That is, we consider the side of a pixel has a length of 1.
Image Analyst

### Image Analyst (view profile)

on 12 Oct 2015
That's too bad. Maybe some day you'll realize and understand the other ways of considering the pixels.
Optically speaking, the pixel center-to-pixel center definition is probably the most accurate, so an image of [0,1,1,1,0] would have a length of 2 rather than 3.
Xen

### Xen (view profile)

on 13 Oct 2015
Thanks for the info (I guess?). Though I was expecting an explanation as to how the length of an object (which could have an abstract shape) relates to the perimeter of it, which is what I was asking in the first place, and maybe how that could give me the number 8 for that particular example.

### David Young (view profile)

on 12 Oct 2015
Edited by David Young

### David Young (view profile)

on 12 Oct 2015

One possible way is like this:
% Example binary image with 3 non-zero pixels
img = false(5); % Use zeros(5) if you prefer
img(3, 2:4) = true; % use 1 instead of true if you prefer
% Get complement of image, with a border round it in case the
% blob is at the boundary
notimg = true(size(img)+2);
notimg(2:end-1, 2:end-1) = ~img;
% Find locations where a non-zero pixel is adjacent to a zero pixel,
% for each cardinal direction in turn
topedges = img & notimg(1:end-2, 2:end-1);
leftedges = img & notimg(2:end-1, 1:end-2);
bottomedges = img & notimg(3:end, 2:end-1);
rightedges = img & notimg(2:end-1, 3:end);
% Sum each set of locations separately, then add to get total perimeter
perim = sum(topedges(:)) + sum(leftedges(:)) + ...
+ sum(bottomedges(:)) + sum(rightedges(:));
% print result
fprintf('Perimeter is %d\n', perim);
This is correct for your example. Before using it you should check it by testing on a wide range of examples. If you find a case for which it is incorrect, please describe it.

Xen

### Xen (view profile)

on 12 Oct 2015
Many thanks David. This works perfectly for a number of examples I've tried. Of course, if the object is unfilled (with a hole) it includes the "internal perimeter", but that's an easy fix. Thanks again.