Serious problem with "createMask" function.

8 vues (au cours des 30 derniers jours)
Meshooo
Meshooo le 25 Mar 2014
Commenté : Meshooo le 28 Mar 2014
Dear all,
I am trying to develop a tool that lets the user to correct manually the contour of an object. The idea is to convert each pixel in the contour and make it a vertex using "impoly" in following code:
Z = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
BW = im2bw(Z);
B = bwboundaries(BW);
b = B{1};
X = b(:, 1);
Y = b(:, 2);
figure, imshow(BW);
hpoly = impoly(gca,[Y, X]);
wait (hpoly)
maskImage = hpoly.createMask();
figure, imshow(maskImage);
figure, imshow(Z);
Now, if you didn't do any change to the vertex and just double clicked inside the square you can notice that "maskImage" and "Z" are not the same!
Any one can tell me why is that? and how can we solve it?
Any help will be appreciated.
Meshoo

Réponse acceptée

Steve Eddins
Steve Eddins le 27 Mar 2014
Here is some code illustrating how to use bwboundaries to get X-Y polygon vertices that work better for mask creation via createMask or poly2mask (which createMask calls). The idea is to get a polygon that includes the centers of the desired mask pixels inside the polygon instead of along its edges. First, here is your code with some graphics to show the area of each pixel and to show the output of bwboundaries going through pixel centers.
BW = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
B = bwboundaries(BW);
b = B{1};
imshow(BW,'InitialMagnification','fit');
hold on
[M,N] = size(BW);
x = [0.5 (N+0.5)];
for k = 1.5:(M-0.5)
y = [k k];
plot(x,y,'Color',[.7 .7 .7],'LineStyle','--');
end
y = [0.5 (M+0.5)];
for k = 1.5:(N-0.5)
x = [k k];
plot(x,y,'Color',[.7 .7 .7],'LineStyle','--');
end
plot(b(:,2),b(:,1),'r')
hold off
And here is modified code that produces X-Y values that do not go directly through pixel centers.
BW3 = imresize(Z,3,'nearest');
B3 = bwboundaries(BW3);
b3 = B3{1};
b3 = (b3 + 1)/3;
imshow(BW,'InitialMagnification','fit');
hold on
[M,N] = size(BW);
x = [0.5 (N+0.5)];
for k = 1.5:(M-0.5)
y = [k k];
plot(x,y,'Color',[.7 .7 .7],'LineStyle','--');
end
y = [0.5 (M+0.5)];
for k = 1.5:(N-0.5)
x = [k k];
plot(x,y,'Color',[.7 .7 .7],'LineStyle','--');
end
plot(b3(:,2),b3(:,1),'r')
hold off
  1 commentaire
Steve Eddins
Steve Eddins le 27 Mar 2014
For an expanded explanation, see my 27-Mar-2014 blog post .

Connectez-vous pour commenter.

Plus de réponses (1)

Steve Eddins
Steve Eddins le 25 Mar 2014
If you are clicking on the centers of the border pixels, then half of the border pixels lie inside the polygonal region you selected and half lie outside. You should click between adjacent pixels instead.
  4 commentaires
Steve Eddins
Steve Eddins le 27 Mar 2014
I believe I did understand the question. I'm sorry that my answer cryptic. The X-Y coordinates that are being passed to impoly enclose a region that includes only half of most the pixels around the border of your mask, and only a quarter of the pixels on the corners. The mask "shift" you are observing is simply a consequence of the tie-breaking rules for determining the output value for a pixel that's half inside and half outside the polygon.
The createMask function for impoly and its cousins uses the Image Processing Toolbox poly2mask, and poly2mask has been designed to have a consistent geometry for pixels that have unit area, as opposed to pixels that are defined a zero-area point. Because the output from bwboundaries traces through pixel centers instead of along pixel edges, it doesn't play nicely with the poly2mask geometric conventions.
For than you probably want to know about poly2mask, see these blog postings:
To get output from bwboundaries that works consistently with poly2mask, try the following:
Upsample the binary by a factor of 3 (imresize(BW,3,'nearest')).
Call bwboundaries
Scale and shift the output of bwboundaries back into the original coordinate system.
I'll experiment with some code to do this.
Meshooo
Meshooo le 28 Mar 2014
Indeed thank you very much Steve for the beautiful explanation and solution. Now it is working very well.

Connectez-vous pour commenter.

Community Treasure Hunt

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

Start Hunting!

Translated by