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

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.

4 件のコメント

Image Analyst
Image Analyst 2015 年 10 月 12 日
That's a matter of definition. You could also say the perimeter is 2 or 4 or 0. What's the length of that object? 3 or 2? It's a matter of definition.
Xen
Xen 2015 年 10 月 12 日
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 2015 年 10 月 12 日
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 2015 年 10 月 13 日
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
David Young 2015 年 10 月 12 日
編集済み: David Young 2015 年 10 月 12 日

0 投票

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.

1 件のコメント

Xen
Xen 2015 年 10 月 12 日
編集済み: Xen 2015 年 10 月 12 日
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.

サインインしてコメントする。

その他の回答 (0 件)

質問済み:

Xen
2015 年 10 月 11 日

コメント済み:

Xen
2015 年 10 月 13 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by