How to crop an image in matlab using interactive tool? - matlab

I want to crop out a window of size 250 X 250 pixels from an image at a specific place. How can I do that? I have seen imtool but I don't know how to control the size of cropping window.

Use imrect, set the size and make it non-resizable, then imcrop, something like:
figure, imshow(I);
h = imrect(gca, [10 10 250 250]);
setResizable(h,0)
rect = wait(h);
% now move to appropriate position
% command line blocked until rectangle is double clicked
I2 = imcrop(I, rect)

This can be done in many ways. For example you may have an image im, and use imtool(im) to find the coordinate (x,y) of the upper right corner of the window you want to crop down to. You can find this coordinate by holding you mouse curser over the pixel and looking in the parentheses in the lower left corner of the imtool-window.
Then you get the cropped image by cropim = im(y+(0:249),x+(0:249)); or cropim = im(y+(0:249),x+(0:249),:); depending on how the image is stored.

Related

Generate a checkerboard pattern of a particular size when printed

I was trying to generate a checkerboard pattern in MATLAB in such a way that when it is printed on a US letter sized paper, the width of each box will be 30 mm.
I tried to change various properties of gcf such as 'Units' and 'PaperSize' etc, but the PDF doesn't print as desired.
I came across several other online methods to generate what I need, but I would like to generate one in MATLAB. Any ideas? Below is sample code.
width = 30;
I = checkerboard(width,5,4);
I = I>0.5;
imshow(I);
saveas(gcf,'checkerboard.pdf')
Matlab can only generate the width based on pixel since Matlab doesn't know the physical dimensions of your screen.
One way is to find the Pixel Per Inch (PPI) of your screen. Here is a website to calculate the PPI by screen dimension and resolution. Then we can calculate the width (the pixel for 30mm) = PPI * 1.1811. (1.1811 inch is equal to 30 mm )
Example, for a screen of PPI = 220 (15.4 in, 2880 * 1800), width=220*1.1811=260.
There are figure properties that start with 'Paper' that specify the size and location of the figure on paper when printed (to PDF or to printer). Here is a list of all figure properties. You'll find these properties under the heading "Printing and Exporting" (see the table on contents on the left pane).
We can use these properties as follows. Note that we don't care about the size of the figure on the screen, so we leave it to the default size. What we do is set the 'PaperPosition' property so that the figure has a certain size when printed. We then create a drawing of a checkerboard pattern that fills the figure. The drawing will thus have the size of the figure itself when printed.
Note how we set the 'PaperSize' property in inches (8.5" x 11" is US Letter), but the 'PaperPosition' property in centimeters (so that we can easily figure out the 3x3 cm squares to draw).
The drawing itself could probably be simplified, but this works. It is much more efficient to draw the pattern using patches (i.e. create a vector drawing) than using an image (i.e. the checkerboard function in OP) when printing to PDF. The output is prettier and the file is smaller. But the same could be done displaying an image.
% Grid size (number of squares)
m = 6; n = 8;
% Square size (in centimeters)
side = 3;
% Create figure and set sizes for printing
figh = figure;
set(figh,'PaperUnits','inches','PaperSize',[8.5 11]);
set(figh,'PaperUnits','centimeters','PaperPosition',[1,1,side*m,side*n]);
% Create axes that fill the figure
axh = axes('Parent',figh,'Units','normalized','Position',[0,0,1,1]);
set(axh,'Color',[1,1,1])
set(axh.XAxis,'Visible','off');
set(axh.YAxis,'Visible','off');
% Draw rectangles
set(axh,'XLim',[0,m],'YLim',[0,n]);
for ii=0:m
for jj=0:n
if mod(ii+jj,2)==0
rectangle('Position',[ii,jj,1,1],'FaceColor',[0,0,0],'LineStyle','none');
end
end
end
% Print to PDF
print(figh,'-dpdf','checkerboard.pdf')

face detection and make it blur

I am having trouble understanding the code about the Matlab
a = imread('Untitled2.png');
faceDetector = vision.CascadeObjectDetector;
bbox=step(faceDetector,a);
for j=1:size(bbox)
xbox=bbox(j,:);
subImage = imcrop(a, xbox);
H = fspecial('disk',10);
blurred = imfilter(subImage,H);
a(xbox(2):xbox(2)+xbox(4),xbox(1):xbox(1)+xbox(3),1:end) = blurred;
end
imshow(a);
Can anyone please kindly explain me that what is the for loop doing? I tried to use my own method to blur the face that I detected, but I just manage to crop out the face and blur the cropped image but I don't know how to put it back to original image. Then I tried to use the source code above I get from internet and the internet source code is able to blur the face and I can't understand the for loop logic. Kindly please explain to me, T^T.
Thanks.
As you can see there :
BBOX = step(detector,I) returns BBOX, an M-by-4 matrix defining M bounding boxes containing the detected objects. This method performs multiscale object detection on the input image, I. Each row of the output matrix, BBOX, contains a four-element vector, [x y width height], that specifies in pixels, the upper-left corner and size of a bounding box. The input image I, must be a grayscale or truecolor (RGB) image.
Are you sure that it's j=1:size(bbox) and not j=1:size(bbox,1) in the code?
Basically, The definition of BBox speaks by itself. The loop just iterates over all the boxes detected..
You then extract the informations about the jth box.
Then you extract the subImage given the position and size of xbox (xbox is a vector containing [x y width height]).
Then you define you filter.
Then you blur your subImage.
Then you override you image a with the blurred subimage using the informations in xbox.
EDIT : If you've already suceeded in blurring the cropped image, you just need to override you input image with your blurred image!

MATLAB - How to zoom in to mouse position

have an image that I would like to zoom in/out when I left/Right-click a point on the image but I do not want to do it using the magnifying glass. Basically, I need a script for what I said above. I have come up with the following script but it only zooms in/out to the center not to the position that I click on.
And if you are asking why I am getting the clicked position using ginput the answer is, I am planning to use this script to edit a binary image! I have removed the lines corresponding to the binary image editing part to avoid any confusion.
hFi= figure; imshow(e);
button=0;
while button~=2
% Get the mouse position on the axes (needed for binary image editing) and button number
[y,x,button]=ginput(1);
% Get the mouse position on the figure
position=get(hFi,'CurrentPoint')
% Set 'CurrentPoint' to the mouse position that was just captured
set(hFi,'CurrentPoint',position)
% Determine if it is a zoom-in or zoom-out
if button==1
zoom(2);
elseif button==3
zoom(0.5);
end
end
I think the command set() does not do anything here but I saw someone suggested that in a forum. Sorry if that looks dumb!
I am assuming you have a matrix as you are asking for the y and x values.
In this way a simple answer would be to display a smaller, or a larger range of values.
Let A be your matrix.
A=rand(1000,1000);
figure,
h=imagesc(A)
axis off
axis image
colormap('gray')
A_range=size(A);
A_zoom=1;
while true
[y,x,button]=ginput(1)
A_center=[x,y];
if button==1
A_zoom=A_zoom/2;
elseif button==3
A_zoom=A_zoom*2;
end
axis([max(x-A_range(1)*A_zoom,1), min(x+A_range(1)*A_zoom,A_range(1)), ...
max(y-A_range(2)*A_zoom,1), min(y+A_range(2)*A_zoom,A_range(2))])
end
Alright, after playing around with imshow and reading through the documentation on internet, I finally came up with what I had been looking for. Thanks to everyone who suggested some ideas, especially ASantosRibeiro who gave me the idea of changing the axis limits.
Basically, I used a combination of commands zoom and xlim/ylim. Therefore, the final code would look like:
hFi= figure; h=imshow(e);
button=0;
zlvl=1;
xl = get(gca,'xlim');
xlen = size(e,2);
yl = get(gca,'ylim');
ylen = size(e,1);
while button~=2
% Get the mouse position on the axes (needed for binary image editing) and button number
[y,x,button]=ginput(1);
% Determine if it is a zoom-in or zoom-out
if button==1
zlvl = zlvl*2;
zoom(2);
elseif button==3
zlvl = zlvl/2;
if zlvl<1, zlvl=1; end % No zoom level smaller than 1
zoom(0.5);
end
% Change the axis limits to where the mouse click has occurred
% and make sure that the display window is within the image dimensions
xlimit = [x-xlen/zlvl/2+0.5 x+xlen/zlvl/2+0.5];
if xlimit(1)<0.5, xlimit=[0.5 xlen/zlvl+0.5]; end
if xlimit(2)>0.5+xlen, xlimit=[xlen-xlen/zlvl+0.5 xlen+0.5]; end
xlim(xlimit);
ylimit = [y-ylen/zlvl/2+0.5 y+ylen/zlvl/2+0.5];
if ylimit(1)<=0.5, ylimit=[0.5 ylen/zlvl+0.5]; end
if ylimit(2)>=0.5+ylen, ylimit=[ylen-ylen/zlvl+0.5 ylen+0.5]; end
ylim(ylimit);
end
This code lets you zoom in/out when you use ginput and you need to use imshow to keep the aspect ratio of image fixed. This becomes very helpful when you need to read coordinates of image pixels and zoom in/out as well. It zooms in when the user left-clicks and zooms out when the user left-clicks. If the middle button is clicked the while loop ends. Other buttons can be added to perform desired operations. For example, I added a few lines of code to edit binary images.
I would like to know your thoughts and if there is any way to make this code more efficient.

How to identify boundaries of a binary image to crop in matlab?

How to identify boundaries of a binary image to crop in matlab?
ie. the input binary image has no noises. only has one black object in white background.
You can use the edge command in MATLAB.
E = edge(I);
I would be an input grayscale or binary image. This will return a binary image with only the edges.
This can provide further assistance:
http://www.mathworks.com/help/images/ref/edge.html
If your image is just black-and-white and has a single object, you can likely make use of the Flood fill algorithm, for which Matlab has built-in support!
Try the imfill function (ref).
This should give you the extents of the object, which would allow you to crop at will.
You can also invert the image, then do regionprops to extract all of the properties for separate objects. You need to invert the image as regionprops assumes that the objects are white while the background is black. A good thing about this approach is that it generalizes for multiple objects and you only need about a few lines of code to do it.
As an example, let's artificially create a circle in the centre of an image that is black on a white background as you have suggested. Let's assume this is also a binary image.
im = true(200, 200);
[X,Y] = meshgrid(1:200, 1:200);
ind = (X-100).^2 + (Y-100).^2 <= 1000;
im(ind) = false;
imshow(im);
This is what your circle will look like:
Now let's go ahead and invert this so that it's a white circle on black background:
imInvert = ~im;
imshow(imInvert);
This is what your inverted circle will look like:
Now, invoke regionprops to find properties of all of the objects in our image. In this case, there should only be one.
s = regionProps(imInvert, 'BoundingBox');
As such, s contains a structure that is 1 element long, and has a single field called BoundingBox. This field is a 4 element array that is structured in the following way:
[x y w h]
x denotes the column/vertical co-ordinate while y denotes the row/horizontal co-ordinate of the top-left corner of the bounding box. w,h are the width and height of the rectangle. Our output of the above code is:
s =
BoundingBox: [68.5000 68.5000 63 63]
This means that the top-left corner of our bounding box is located at (x,y) = (68.5,68.5), and has a width and height of 63 each. Therefore, the span of our bounding box goes from rows (68.5,131.5) and columns (68.5,131.5). To make sure that we have the right bounding box, you can draw a rectangle around our shape by using the rectangle command.
imshow(im);
rectangle('Position', s.BoundingBox);
This is what your image will look like with a rectangle drawn around the object. As you can see, the bounding box given from regionprops is the minimum spanning bounding box required to fully encapsulate the object.
If you wish to crop the object, you can do the following:
imCrop = imcrop(imInvert, s.BoundingBox);
This should give you the cropped image that is defined by the bounding box that we talked about earlier.
Hope this is what you're looking for. Good luck!

find position of image surranded by black area

There is an image, surrounded by black region, I would like to find the exact locaton of this image (which is surrounded by black region). I mean the coordinates of four corners of this image. Thanks.
You could apply a second derivative mask on your image which will then accurately pick up the points at which the colour goes from black to the content of the picture. You can then extract the first and last row and column each and you've got your coordinates.
If you are in matlab:
Mask out the black area. Either try:
Image = logical(Image)
Or find the intensity of a black voxel (probably zero) and say:
Image = ind2sub(size(Image), find(Image ~= blackPixelIntensity))
Once you have the binary non-black part of the image (so just the object and not the background), you just want to find the min, max corners of each voxel. Say:
[x y] = ind2sub(size(Image), find(Image ~= 0))
c1 = [min(x) min(y)]
c2 = [max(x) min(y)]
c3 = [max(x) max(y)]
c4 = [min(x) min(y)]
Where c1,...,c4 are your corners :)
Lemme know about any syntax error as I don't have access to matlab atm.
tylerthemiler
Edit: if you simply want the entire perimeter of the non-black part of the image, just do whichever of the first two lines of code above works, and then say:
Imperim = bwperim(Image)
Edit2: Note that Image is the 2D array, you can use whatever you want to load in the jpg :P