Image snip and paste. Draw a polygone on an image, then click and drag to move that part of the image around. Bonus points for resize and rotate.
5 次查看(过去 30 天)
显示 更早的评论
Hi,
I'm essentially trying to recreate the functionality of the select tool in MS Paint, but using a polygone rather than a rectangle. I want the user to load an image, draw a polygone over the image, then click and drag that polygone to cut that section out of the image and move it somewhere else.
bonus points, as later I want the user to be able to resize and rotate that polygone. Also place mutiple polygons moving different parts of the same image.
Below is the best code I have so far. It loads tire.jpg but feel free to swap that for any other image.
The user can select and draw the polygone, the commented out lines of code after defining the polygon_mask test that the image is cut from original image in the shape of the polygone correctly. Which it is. That works fine.
The function roi_moving seems to work well too. Dragging the cut section of image within the polygone, and a black section is left behind at the polygones orignal location.
roi_moved seems to be the problem. It doesn't paste the polygone down after the user has finished moving it. So I tried using the code from roi_moving at the end of roi_moved as shown at the bottom but that didn't work.
I also tried a whole seperate approach using addlistener functions.
Finally I've tried asking ChatGPT but to no avail.
I'm also getting the below warning message coming from MATLAB.
Error Message: (shows as code, it's actually orange error text from the command window.
> In images.roi.internal/ROI/dragROI
In images.roi.internal.ROI
Warning: Error occurred while executing the listener callback for event MovingROI defined for class images.roi.Polygon:
Unable to perform assignment because the left and right sides have a different number of elements.
Error in test3>roi_moving (line 52)
new_image(repmat(new_polygon_mask, [1, 1, size(I, 3)])) = I(repmat(temp_mask, [1, 1, size(I, 3)]));
Error in test3>@(src,event)roi_moving(src,event,h_image,I) (line 28)
lh_moving = addlistener(h, 'MovingROI', @(src, event)roi_moving(src, event, h_image, I));
Error in images.roi.internal.ROI/dragROI
Error in images.roi.internal.ROI
> In images.roi.internal/ROI/dragROI
In images.roi.internal.ROI
%The best code I have so far.
% this is really close. It moves the image but doesn't drop it off where it should be
I = imread('tire.jpg');
figure;
h_image = imshow(I);
hold on;
% Allow the user to create and move polygonal ROIs
h = drawpolygon;
if ~isvalid(h)
return
end
pos = h.Position;
% Round the position values to integers for indexing
pos_int = round(pos);
% Generate a mask from the polygon
polygon_mask = poly2mask(pos_int(:,1), pos_int(:,2), size(I, 1), size(I, 2));
% % Create an image section from the polygon
% section = I(min(pos_int(:,2)):max(pos_int(:,2)), min(pos_int(:,1)):max(pos_int(:,1)), :);
% figure
% h_section = imshow(section); % show rectancle of outer edge of polygone
% set(h_section, 'AlphaData', polygon_mask(min(pos_int(:,2)):max(pos_int(:,2)), min(pos_int(:,1)):max(pos_int(:,1)))); %show polygone only
% Set up listeners for the MovingROI and ROIMoved events
lh_moving = addlistener(h, 'MovingROI', @(src, event)roi_moving(src, event, h_image, I));
lh_moved = addlistener(h, 'ROIMoved', @(src, event)roi_moved(src, event, h_image, I));
% Callback function for when the ROI is moving
% Callback function for when the ROI is moving
function roi_moving(src, ~, h_image, I)
% Get the current position of the polygon
pos = src.Position;
% Round the position values to integers for indexing
pos_int = round(pos);
% Generate a mask from the new polygon position
new_polygon_mask = poly2mask(pos_int(:,1), pos_int(:,2), size(I, 1), size(I, 2));
% Get the old polygon_mask
old_polygon_mask = src.UserData;
% Create a new mask of the same size as I
temp_mask = false(size(I, 1), size(I, 2));
temp_mask(1:size(old_polygon_mask, 1), 1:size(old_polygon_mask, 2)) = old_polygon_mask;
% Create a new image with the section cut from the original image
new_image = I;
new_image(repmat(new_polygon_mask, [1, 1, size(I, 3)])) = I(repmat(temp_mask, [1, 1, size(I, 3)]));
new_image(repmat(temp_mask, [1, 1, size(I, 3)])) = 0;
% Update the displayed image
set(h_image, 'CData', new_image);
end
% Callback function for when the ROI has been moved
function roi_moved(src, ~, h_image, I)
% Get the current position of the polygon
pos = src.Position;
% Round the position values to integers for indexing
pos_int = round(pos);
% Generate a mask from the new polygon position
new_polygon_mask = poly2mask(pos_int(:,1), pos_int(:,2), size(I, 1), size(I, 2));
% Store the new_polygon_mask in the ROI's UserData property
src.UserData = new_polygon_mask;
% Update the displayed image
set(h_image, 'CData', I);
end
Modified roi_moved:
% Callback function for when the ROI has been moved
function roi_moved(src, ~, h_image, I)
% Get the current position of the polygon
pos = src.Position;
% Round the position values to integers for indexing
pos_int = round(pos);
% Generate a mask from the new polygon position
new_polygon_mask = poly2mask(pos_int(:,1), pos_int(:,2), size(I, 1), size(I, 2));
% Get the old polygon_mask
old_polygon_mask = src.UserData;
% Create a new mask of the same size as I
temp_mask = false(size(I, 1), size(I, 2));
temp_mask(1:size(old_polygon_mask, 1), 1:size(old_polygon_mask, 2)) = old_polygon_mask;
% Create a new image with the section cut from the original image
new_image = I;
new_image(repmat(new_polygon_mask, [1, 1, size(I, 3)])) = I(repmat(temp_mask, [1, 1, size(I, 3)]));
new_image(repmat(temp_mask, [1, 1, size(I, 3)])) = 0;
% Update the displayed image
set(h_image, 'CData', new_image);
end
0 个评论
回答(1 个)
Image Analyst
2023-5-1
See attached copy and paste demos.
6 个评论
Image Analyst
2023-5-2
2)
mask = uint8(CurrentPoly_Original_mask);
or am I not understanding something?
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!