Creating masks of open lines with imfreehand and impoly ROI tools

8 views (last 30 days)
With both the imfreehand and impoly tools one can set the 'Closed' line property to false which allows for the creation of open non straight lines. Surprisingly, masks created with these tools using createMask are always closed even when the 'Closed' property is set to false. This appears to be a bug?
I would like to create masks of non straight lines which precludes using the imline tool. Any suggestions on how to achieve this given the stated issues with the imfreehand and impoly tools? Thanks for any assistance.

Accepted Answer

Teja Muppirala
Teja Muppirala on 30 Jul 2012
If I understand you correclty, you want to create an image of the line, without closing the curve. That's certainly doable.
I = imread('peppers.png');
imshow(I);
M = imfreehand(gca,'Closed',0);
F = false(size(M.createMask));
P0 = M.getPosition;
D = round([0; cumsum(sum(abs(diff(P0)),2))]); % Need the distance between points...
P = interp1(D,P0,D(1):.5:D(end)); % ...to close the gaps
P = unique(round(P),'rows');
S = sub2ind(size(I),P(:,2),P(:,1));
F(S) = true;
figure;
imshow(F);
  4 Comments
Neil
Neil on 30 Jul 2012
I actually tried to put one in yesterday but couldn't. I think that createMask should logically respect the prior properties set with imfreehand and impoly so I will submit a change request for a future update.
Neil
Neil on 2 Nov 2012
When I use Teja's code on a small image (56x59 pixels) I get the following message:
_|Error using griddedInterpolant. The point coordinates are not sequenced in strict monotonic order.
Error in interp1>Interp1D (line 335) F = griddedInterpolant(X,V(:,1),method); | _
I think this has to do with the fact the small image is automatically zoomed for display and therefore interpolated. This appears to trip the call to interp1 in Teja's code. I think making the onscreen axis pixel size the same size as the image might take care of the problem but then I wouldn't really be able to see the image. Any help on how to use | interp1| on zoomed images?

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 29 Jul 2012
A mask is an area. If you want lines as a mask, like just a one pixel wide path, then you'd have to set those pixels from the x,y coordinates that those functions return. If you want non-straight "lines" then use imfreehand to draw curves of arbitrary shape. Why do you want a "mask" of just a single pixel wide path anyway? You have the coordinates so why do you now need a binary image of those coordinates?
  5 Comments
Image Analyst
Image Analyst on 29 Jul 2012
Edited: Image Analyst on 29 Jul 2012
My very first responses addressed your initial questions. I said basically, that's not how they work. Then I gave you two workarounds (imline, with demo code, and imfreehand) to do what you want to do. So you can either do one of the workarounds and move on, or put in a feature request with the Mathworks and wait for some version in the future that may do it the way you think it should work.
You can try this imfreehand code below, but be aware that imfreehand doesn't give adjacent coordinates, particularly if you draw fast, so in that case you might have to us imline anyway (in between the coordinates that imfreehand gives you) to make sure there are no gaps in the drawn curve.
% Demo to have the user freehand draw an irregular shape over
% a gray scale image, and burn the curve points into the image.
clc; % Clear command window.
clear; % Delete all variables.
close all; % Close all figure windows except those created by imtool.
imtool close all; % Close all figure windows created by imtool.
workspace; % Make sure the workspace panel is showing.
fontSize = 16;
% Read in a standard MATLAB gray scale demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
baseFileName = 'cameraman.tif';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% File doesn't exist -- didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
imshow(grayImage, []);
axis on;
title('Original Grayscale Image', 'FontSize', fontSize);
set(gcf, 'Position', get(0,'Screensize')); % Maximize figure.
message = sprintf('Left click and hold to begin drawing.\nSimply lift the mouse button to finish');
uiwait(msgbox(message));
hFH = imfreehand();
% Create a binary image ("mask") from the ROI object.
binaryImage = hFH.createMask();
xy = int32(hFH.getPosition);
% Now make it smaller so we can show more images.
subplot(2, 2, 1);
imshow(grayImage, []);
axis on;
title('Original Grayscale Image', 'FontSize', fontSize);
% Display the freehand mask just for fun - we won't use binaryImage.
binaryImage = false(size(grayImage));
linearIndexes = sub2ind(size(grayImage), xy(:, 2), xy(:, 1));
binaryImage(linearIndexes) = true;
subplot(2, 2, 2);
imshow(binaryImage);
axis on;
title('Binary mask of the region', 'FontSize', fontSize);
% Display it.
subplot(2, 2, 3);
grayImage(linearIndexes) = 255;
imshow(grayImage);
axis on;
title('Grayscale Image with freehand curve burned in', 'FontSize', fontSize);
Neil
Neil on 30 Jul 2012
Thanks again for your response Image Analyst. I had tried, almost identically, the various solutions you proposed prior to posting my question. These solutions did not satisfy the specific needs I outlined. I was hoping that there might be another simple solution so I'll just move on.
If anyone else has other ideas as to how I could achieve my specific objectives I'd be glad to hear it.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!