4

One can mark the boundary of a binary image by bwboundaries function of MATLAB.

What should be done for obtaining boundaries of all segments as a binary image?

I have segmented an image and want to know if there is a way to mark boundaries between each neighbouring segment without applying morphological operations on each segment.

I have added images to illustrate what i want to do. Actually i want to obtain a binary image that keeps pink boundary marker pixels between all segments. Thus, I can overlay them with original image by the help of imoverlay function of Steve Eddins.

Random colored labeling of segmentation result:

enter image description here

Roughly-marked pink boundaries between segments:

enter image description here

Gulcan
  • 77
  • 2
  • 8

3 Answers3

5

You can find the region boundaries using a range filter, which finds the intensity range within each pixel's neighborhood. This takes advantage of the fact that the label matrix only has non-zero range at the region boundaries.

im = imread('https://i.stack.imgur.com/qPiA3.png');
boundaries = rangefilt(im,ones(3)) > 0;
imoverlay(label2rgb(im),boundaries,[0 0 0]);

These edges are also two pixels wide. Actually, I think the edges have to be two pixels wide; otherwise the regions will "lose" pixels to the border non-uniformly.

reve_etrange
  • 2,561
  • 1
  • 22
  • 36
  • Thanks for your solution. It is a nice catch about the situation, you're right. I realized your solution is slightly faster than the solution proposed with erosion-dilation formerly. – Gulcan Jan 29 '12 at 00:37
3

Since erosion and dilation work on non-binary images as well, you can write

img = imread('https://i.stack.imgur.com/qPiA3.png');
ei = imerode(img,ones(3));
di = imdilate(img,ones(3));
boundaries = ei~=img | di~=img;

This results in a bw image that has a boundary at the edge of each colored region (thus, the boundary line will be two pixels wide).

enter image description here

Note that this will not return an ordered list of pixels as bwboundaries, but rather a logical mask like bwperim, which is what imoverlay needs as input.

Jonas
  • 74,690
  • 10
  • 137
  • 177
  • Thanks a lot. I missed the first fact you mentioned about erosion dilation. That helps a lot. – Gulcan Jan 29 '12 at 00:18
  • @Gulcan: If you're concerned about speed, you may want to use `strel` instead of `ones` for the mask, i.e. `strel('square',3)` instead of `ones(3)`. This will use a separable filter that is faster. – Jonas Jan 29 '12 at 04:18
1

As a round-about way, I thought of making use of edge function of MATLAB. First, I need to apply something like a label2gray operation. labels is the segmentation output (first image provided in the question) in the code below.

grayLabels = mat2gray(255* double(labels) ./ double(max(labels(:)))); %label2gray
bw_boundaries = edge(grayLabels,0.001);
Gulcan
  • 77
  • 2
  • 8
  • For this approach, just normalize the label matrix: `nim = im - min(im(:)); nim = nim/max(nim(:));`. Nearly all of MATLAB's image processing functions work on normalized matrices of type double. – reve_etrange Jan 29 '12 at 01:45
  • Secondly, in this case the gradient methods don't find all the edge pixels. Display the overlay and take an up-close look at the region corners. – reve_etrange Jan 29 '12 at 01:49
  • Yeah, I'm aware of that :) i need to adjust 0.001 hard threshold according to max number assigned in labeled image. – Gulcan Jan 29 '12 at 22:29