Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
crop image by polygon

Subject: crop image by polygon

From: Clint_E

Date: 9 Nov, 2010 10:59:04

Message: 1 of 10

Dear all,

I have a jpg image I want to crop by an arbitrary polygon. I'm trying to do it by imcrop: imcrop(X, map, rect), but it only allows to specify a rectangular area in rect and I have more complex polygons... In detail, I want to extract some features from an ortho-image by the polygons of the relative shapefile, here my code:

%%read orthophoto
[X cmap] = imread('orthophoto_1.jpg');
R = worldfileread('orthophoto_1.jgw');

%%read shapefile buildings
[s, a] = shaperead('buildings.shp');

s is:

61555x1 struct array with fields:
    Geometry
    BoundingBox
    X
    Y

and if I take s(1,1) for instance I have my polygon, which I want to crop:

    Geometry: 'Polygon'
    BoundingBox: [2x2 double]
    X: [1x11 double]
    Y: [1x11 double]

I would like to do something like:

%%crop the feature
feature_1 = imcrop(X, map, s(1,1).X, s(1,1).Y);

and then save it to new jpg.
Maybe I could use roipoly or impoly to pass the polygon to imcrop?
Any help would be extremely appreciated! Thanks in advance!
Luca

Subject: crop image by polygon

From: ImageAnalyst

Date: 9 Nov, 2010 11:24:10

Message: 2 of 10

Just get the x coordinates of your polygon, and find the min and max
with the min() and max() functions. Do the same for your y vertices
coordinates. Then you have your cropping rectangle
[xMin yMin abs(xMax-xMin+1) abs(yMax-yMin+1)]

Subject: crop image by polygon

From: Clint_E

Date: 9 Nov, 2010 14:09:04

Message: 3 of 10

ImageAnalyst, thanks for your reply!

I agree I can crop it that way, but it doesn't solve my problem as I want to extract the exact area of a general-shaped polygon (which is not a rectangle). This would be the starting point, extracting a submatrix of the bounding box, but then I have to go one more step to keep the matrix elements within my shape and "remove" the rest.. roipoly could be good, but requires knowledge of matrix indices to contruct the shape..I have x and y coordinates instead (obviously in consistent geo-reference system)..

Subject: crop image by polygon

From: Sean

Date: 9 Nov, 2010 14:45:04

Message: 4 of 10

"Clint_E " <luca_bergamasco@hotmail.com> wrote in message <ibbkm0$l5c$1@fred.mathworks.com>...
> ImageAnalyst, thanks for your reply!
>
> I agree I can crop it that way, but it doesn't solve my problem as I want to extract the exact area of a general-shaped polygon (which is not a rectangle). This would be the starting point, extracting a submatrix of the bounding box, but then I have to go one more step to keep the matrix elements within my shape and "remove" the rest.. roipoly could be good, but requires knowledge of matrix indices to contruct the shape..I have x and y coordinates instead (obviously in consistent geo-reference system)..

a hint:
doc poly2mask

Subject: crop image by polygon

From: ImageAnalyst

Date: 9 Nov, 2010 16:14:49

Message: 5 of 10

Clint_E :
You could use polyarea if you just wanted the area and you had the
vertex coordinates. If you want other stuff, like a masked image,
etc. take a look at this demo:

% Change the current folder to the folder of this m-file.
if(~isdeployed)
cd(fileparts(which(mfilename)));
end
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 = 20;

% Read in standard MATLAB gray scale demo image.
grayImage = imread('cameraman.tif');
subplot(2, 2, 1);
imshow(grayImage, []);
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();
% Display the freehand mask.
subplot(2, 2, 2);
imshow(binaryImage);
title('Binary mask of the region', 'FontSize', fontSize);

% Calculate the area, in pixels, that they drew.
numberOfPixels1 = sum(binaryImage(:))
% Another way to calculate it that takes fractional pixels into
account.
numberOfPixels2 = bwarea(binaryImage)

% Get coordinates of the boundary of the freehand drawn region.
structBoundaries = bwboundaries(binaryImage);
xy=structBoundaries{1}; % Get n by 2 array of x,y coordinates.
x = xy(:, 2); % Columns.
y = xy(:, 1); % Rows.
subplot(2, 2, 1); % Plot over original image.
hold on; % Don't blow away the image.
plot(x, y, 'LineWidth', 2);

% Burn line into image by setting it to 255 wherever the mask is true.
burnedImage = grayImage;
burnedImage(binaryImage) = 255;
% Display the image with the mask "burned in."
subplot(2, 2, 3);
imshow(burnedImage);
title('New image with mask burned into image', 'FontSize', fontSize);

% Mask the image and display it.
% Will keep only the part of the image that's inside the mask, zero
outside mask.
maskedImage = grayImage;
maskedImage(~binaryImage) = 0;
subplot(2, 2, 4);
imshow(maskedImage);
title('Masked Image', 'FontSize', fontSize);

% Calculate the mean
meanGL = mean(maskedImage(binaryImage));

% Report results.
message = sprintf('Mean value within drawn area = %.3f\nNumber of
pixels = %d\nArea in pixels = %.2f', ...
    meanGL, numberOfPixels1, numberOfPixels2);
msgbox(message);

Subject: crop image by polygon

From: Clint_E

Date: 12 Nov, 2010 11:03:05

Message: 6 of 10

Guys, thanks for your hints and help.. I finally did it like this (if anyone interested):

im_crop is your image
vertex_x is the vector of x-coordinates of your polygon
vertex_y is the vector of y-coordinates of your polygon

im_crop_size=size(im_crop);
mask = poly2mask(vertex_x,vertex_y,im_crop_size(1,1),im_crop_size(1,2));

Split your RGB image in bands, mask each of them and re-build the image (set background to black):

R=im_crop(:,:,1);
G=im_crop(:,:,2);
B=im_crop(:,:,3);
R(~mask)=0;
G(~mask)=0;
B(~mask)=0;
masked_im = cat(3,R,G,B);

Cya!

Subject: crop image by polygon

From: ImageAnalyst

Date: 12 Nov, 2010 11:19:00

Message: 7 of 10

OK, but that's usually called masking, not cropping.

Subject: crop image by polygon

From: Clint_E

Date: 12 Nov, 2010 11:29:08

Message: 8 of 10

Sorry, I'm a newbie in image processing..

Subject: crop image by polygon

From: Sean

Date: 12 Nov, 2010 12:16:04

Message: 9 of 10

"Clint_E " <luca_bergamasco@hotmail.com> wrote in message <ibj6t9$lmb$1@fred.mathworks.com>...
> Guys, thanks for your hints and help.. I finally did it like this (if anyone interested):
>
> im_crop is your image
> vertex_x is the vector of x-coordinates of your polygon
> vertex_y is the vector of y-coordinates of your polygon
>
> im_crop_size=size(im_crop);
> mask = poly2mask(vertex_x,vertex_y,im_crop_size(1,1),im_crop_size(1,2));
>
> Split your RGB image in bands, mask each of them and re-build the image (set background to black):
>
> R=im_crop(:,:,1);
> G=im_crop(:,:,2);
> B=im_crop(:,:,3);
> R(~mask)=0;
> G(~mask)=0;
> B(~mask)=0;
> masked_im = cat(3,R,G,B);
>
> Cya!

You could also do this with bsxfun or repmat. Just for your knowledge:

masked_im2 = bsxfun(@times,im_crop,cast(mask,class(im_crop)))

masked_im3 = im_crop.*repmat(cast(mask,class(im_crop)),[1 1 3]);

Subject: crop image by polygon

From: epsilon

Date: 7 Feb, 2011 20:49:04

Message: 10 of 10

"Sean " <sean.dewolski@nospamplease.umit.maine.edu> wrote in message <ibjb64$nkk$1@fred.mathworks.com>...
> "Clint_E " <luca_bergamasco@hotmail.com> wrote in message <ibj6t9$lmb$1@fred.mathworks.com>...
> > Guys, thanks for your hints and help.. I finally did it like this (if anyone interested):
> >
> > im_crop is your image
> > vertex_x is the vector of x-coordinates of your polygon
> > vertex_y is the vector of y-coordinates of your polygon
> >
> > im_crop_size=size(im_crop);
> > mask = poly2mask(vertex_x,vertex_y,im_crop_size(1,1),im_crop_size(1,2));
> >
> > Split your RGB image in bands, mask each of them and re-build the image (set background to black):
> >
> > R=im_crop(:,:,1);
> > G=im_crop(:,:,2);
> > B=im_crop(:,:,3);
> > R(~mask)=0;
> > G(~mask)=0;
> > B(~mask)=0;
> > masked_im = cat(3,R,G,B);
> >
> > Cya!
>
> You could also do this with bsxfun or repmat. Just for your knowledge:
>
> masked_im2 = bsxfun(@times,im_crop,cast(mask,class(im_crop)))
>
> masked_im3 = im_crop.*repmat(cast(mask,class(im_crop)),[1 1 3]);


hi,
i want to say thanks for your question and the solution. because i'm trying to do this veryy very long time and i can't do it. then tonight i find your message, i apply it to my code and it works. Thank you...
i apologize you for my english.

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us