MATLAB Answers

Dilate a line and color both sides

11 views (last 30 days)
Philip on 28 Nov 2011
Does anyone know if it's possible to dilate a line in an image, such that one side of the original line is colored red, and the other side is colored yellow?
The line segment can be at any orientation so it is not sufficient to just say "the top half should be red, and the bottom half should be yellow"... so I need to find a more appropriate way.
I am using 'imdilate' to dilate the line:
dilated_edge = imdilate(line_segment,strel('square',60));
Many thanks for your help and suggestions.


Show 3 older comments
Walter Roberson
Walter Roberson on 28 Nov 2011
There is a standard algorithm for determining which side of a continuous line that one is on: if you proceeds in a straight line, then if you have crossed the line an even number of times then you are on the "first" side of the line.
Image Analyst
Image Analyst on 28 Nov 2011
So it's really a curve, not a straight line. Which side goes red and which side goes yellow, if it matters? Can you upload an image illustrating your desired result somewhere?
Philip on 28 Nov 2011
It doesn't matter which side goes red, and which goes yellow. So, the desired output from the above example is:

Sign in to comment.

Answers (2)

Image Analyst
Image Analyst on 28 Nov 2011
You can dilate the curve first so that you have a big fat wormy shape. Then you'd have to extend the ends of the curve so that it chops the big wormy shape into two halves - this is the hard part - subtract the extended line from the wormy shape. Then you can use this code to label and color the two halves of the worm.
% Label each blob so we can make measurements of it
[labeledImage numberOfBlobs] = bwlabel(binaryImage, 8);
coloredLabels = label2rgb (labeledImage, 'hsv', 'k', 'shuffle'); % pseudo random color labels


Philip on 28 Nov 2011
Thanks, that makes good sense! Instead of extending the curve to the end of the wormy shape, I would prefer to make the wormy shape smaller to meet the curve... But I think this is just as hard; maybe harder!
The bwlabel function looks like it will work well when I get to this stage though. Thanks.
Image Analyst
Image Analyst on 29 Nov 2011
You can do that, and I have. Basically you have to find the end points, and fit a line to the last several coordinates. Then get the equation for the perpendicular line (not hard - it's just -1 over the slope, etc.). Then somehow separate the rounded tip of the worm from the body of the worm by subtracting the perpendicular line. Then bwlabel, regionprops to find centroids, and toss out the blob that has a centroid within a kernel width or so of the endpoints. A bit tricky but it can be done and should be fairly fast.

Sign in to comment.

David Young
David Young on 29 Nov 2011
Building on Image Analyst's answer, here's another thought about how to trim the ends of the worm.
The basic idea is to erode each end of the worm using a mask that is derived from the original image. This assumes that the curve in the image is reasonably smooth on a scale comparable to the worm thickness, but if it isn't, the process as a whole probably doesn't make a lot of sense.
The code below demonstrates the idea. I've taken the simple case of a straight line but it should be OK with a curve, as long as the curve is connected. The core operation is to extract a patch of the original image centred on a line end, rotate it through 180 degrees, and erode the same end of the worm with it, cutting it back so that the line meets the boundary.
I haven't tested this very thoroughly - it may need more work to make it robust for all reasonable cases. The factor of 1.2 times the dilation radius to get the region to erode at the end of the worm is empirical - it should be easy enough to work out a well-founded value geometrically, but I haven't got round to that.
Also, I have assumed that the worm does not get too close to the boundaries of the image. It would be easy to fix the code to deal with this problem by using exindex to cut out the patches.
% end points of line - assumed given
x1 = 50;
y1 = 150;
x2 = 150;
y2 = 50;
% synthetic data. Just a straight line for testing, but this ought to be ok
% with a curve
im = false(200, 200);
im(sub2ind(size(im), y1:-1:y2, x1:x2)) = true;
% dilate to make worm
r = 30;
diskstruc = strel('disk', r, 0);
dil = imdilate(im, diskstruc);
% get a disk of radius rad in order to make the line-end mask
disk = false(2*r+1);
disk(r+1, r+1) = true;
disk = imdilate(disk, diskstruc);
% erode ends of worm
r2 = ceil(1.2*r); % 1.2 is a fudge factor. Needs to be thought through.
mask = im(y1-r:y1+r, x1-r:x1+r) & disk; % one end of line
reg = dil(y1-r2:y1+r2, x1-r2:x1+r2); % same end of worm
erod = imerode(reg, rot90(mask, 2)); % eroded bit of worm
dil(y1-r2:y1+r2, x1-r2:x1+r2) = erod; % put back in worm image
mask = im(y2-r:y2+r, x2-r:x2+r) & disk; % other end of line ...
reg = dil(y2-r2:y2+r2, x2-r2:x2+r2);
erod = imerode(reg, rot90(mask, 2));
dil(y2-r2:y2+r2, x2-r2:x2+r2) = erod;
% split and paint
splt = dil & ~im;
% colour
col = label2rgb(bwlabel(splt, 4));
figure; imshow(col);


Sign in to comment.

Community Treasure Hunt

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

Start Hunting!

Translated by