MATLAB Answers

0

Overlapping region of a single ROI is excluded by the mask

Asked by Alessandro on 1 Apr 2015
Latest activity Commented on by Image Analyst
on 11 May 2015
Dear all
I need to draw an ROI where I select a region that partially overlaps with the region already delimited by the same ROI line. This is for example the case when you want to draw a closed ring-shaped ROI with a single line.
The problem is that the overlapping area is excluded by the mask.
I tried using roipoly, imfreehand, poly2mask, but they all exclude the overlapping region and I do not find an easy way to achieve this task (I also tried with bwboundaries, bwtraceboundary, inpolygon).
Any suggestion would be very appreciated, thanks!

  1 Comment

I have also tried the nice mpoly2mask function from File Exchange but it's also not working in this case.
The easiest I've come up with (though a bit tedious in my case) is by drawing two separate ROIs and then subtract them.

Sign in to comment.

2 Answers

Answer by Image Analyst
on 18 Apr 2015
 Accepted Answer

Simply use roipolyold():
binaryImage = roipolyold();
Here's a full demo to produce the above picture:
% Display something so we can draw on it.
grayImage = uint8(255*mat2gray(peaks(300)));
subplot(2,2,1);
imshow(grayImage, []);
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
message = sprintf('Draw your overlapping region with left clicks.\nRight click the last point to finish it.');
uiwait(helpdlg(message));
[roiMask, x, y] = roipolyold;
% Draw the outline over the image.
hold on;
plot(x, y, 'r-', 'LineWidth', 2);
subplot(2,2, 2);
imshow(roiMask);
% Mask the image and display it.
outputImage = grayImage; % Initialize
outputImage(~roiMask) = 0; % Mask
subplot(2,2, 3);
imshow(outputImage);

  2 Comments

This is exactly what I was looking for. Strangely enough, I didn't find the existance of this roipolyold function with my searches on the web. So thank you very much Image Analysist!
That's because it's been deprecated. I've told the image processing team that I don't want it to be, and that it should be an option for roipoly() or impoly().

Sign in to comment.


Answer by Sven
on 18 Apr 2015

Hi Alessandro,
When you say that you "want to draw a closed ring shape with a single line", we might step-by-step reinterpret this as:
"I want to draw an object that has 2 lines, but only use 1 line"
and then:
"I want to draw one line with an array of points, but I want a program to (somehow) automatically detect one (or more?) of these points to split at, and pretend that I actually drew two lines".
If you were to define your question with actual input data to go with the diagrams you made, I imagine you'd have simply an N-by-2 array of points. From there, I imagine that the answer would be to somehow detect a "special" location in your N points, and then insert a [nan nan] at that location, finally send the result to mpoly2mask.
So probably the reason why this question hasn't gotten an answer yet, is that before anyone tries to answer it (magically knowing which place to split your single array of points without more information will be very tricky), they'd probably want to convince you to change the question definition itself.
For instance, why exactly, must it all be drawn in a single line? It seems in your question that you are defining that you want to draw a closed ring. This type of object is naturally described by 2 lines. It would be much much simpler to make a small (but logical) modification to your program to ask the user to draw 2 lines, rather than to try to guess which part of their drawing was meant to be the inner part and which part of their drawing was meant to be the outer part. For instance in the diagram you provided, there are actually 3 separate self-intersection locations in your line, and it's not clear for a program to choose which one(s) to use.
Making a change to your question instead, you'd basically have:
innerCircle = ... whatever code you have gets a single XY line
outerCircle = ... whatever code you have gets a single XY line
A = false(2); % Make a connectivity matrix
A(1,2) = 1; % The first object is removed from the second
BW = mpoly2mask({innerCircle outerCircle}, A);
That's just 5 straight-forward lines of code. Any attempt to guess the intended break between inner and outer circle will certainly be much more difficult and complicated.
Hope this answer helps you out,
Sven

  1 Comment

Thanks a lot Sven for your reply. Using two lines is how I would have solved it indeed. Nonetheless, for my specific needs, the roipolyold function is more convenient.

Sign in to comment.