MATLAB - Splitting an image converts the blocks into grayscale - matlab

Using MATLAB, I am trying to convert a randomly sized image into four equal blocks. I am working with "for" loops to create blocks. The problem I am facing is that these blocks are being converted into gray scale whereas I want the blocks to retain their original form i.e. RGB channel. Here is the code I am using:
clear all;
img1 = imread('ABC.png');
[rs, cols, colorchan] = size(img1);
rnew = int32(rs/2);
cnew = int32(cols/2);
for i = 1:4
for j = 1:4
imgij = img1((i-1)*rnew+1:i*rnew, (j-1)*cnew+1:j*cnew);
figure();
imshow(imgij);
%do some other stuff here%
end
end
I am new to MATLAB and that's the best I could do myself. Can somebody please tell me how to retain the original form of every block of the parent image? Any help will be highly appreciated.

You have considered only the width and height of the image. But actually for a colour image, colour is the 3rd dimension in Matlab. Try the following code.
img = imread('onion.png');
figure; imshow(img);
w = size(img,2); % width of the original image
h = size(img,1); % height of the original image
wm = floor(w/2); % middle of the width
hm = floor(h/2); % middle of the height
figure;
imgtl = img(1:hm,1:wm,:); % top left image
subplot(2,2,1); imshow(imgtl);
imgtr = img(1:hm,wm+1:w,:); % top right image
subplot(2,2,2); imshow(imgtr);
imgbl = img(hm+1:h,1:wm,:); % bottom left image
subplot(2,2,3); imshow(imgbl);
imgbr = img(hm+1:h,wm+1:w,:); % bottom right image
subplot(2,2,4); imshow(imgbr);
Original image:
Partitioned image:

Related

Changing Bounding Box Dimensions

New to Matlab here. I'm trying to implement some code to detect a face in an image and crop it. I have the script running, but the bounding box that it places around the detected face is a bit small. Is there any way to change the dimensions of the bounding box to capture more of the faces?
clc;
% cd into the a folder with pictures
cd 'C:\Users\abc\Desktop\folder'
files = dir('*.jpg');
for file = files'
img = imread(file.name);
figure(1),imshow(img);
FaceDetect = vision.CascadeObjectDetector;
FaceDetect.MergeThreshold = 7;
BB = step(FaceDetect,img);
figure(2),imshow(img);
for i = 1:size(BB,1)
rectangle('Position',BB(i,:),'LineWidth',2,'LineStyle','- ','EdgeColor','r');
end
for i = 1:size(BB,1)
rectangle('Position',BB(i,:),'LineWidth',2,'LineStyle','- ','EdgeColor','r');
J = imcrop(img,BB(i,:));
figure(3);
imshow(J);
a = 'edited\'
b = file.name
output = strcat(a,b);
imwrite(J,output);
end
%Code End
end
Currently, the script finds a face like so:
And outputs an image such as this:
This is good, I just want to extend the boundaries of the cropping zone to capture more of the face (e.g., hair and chin).
From the MATLAB rectangle function documentation.
rectangle('Position',pos) creates a rectangle in 2-D coordinates.
Specify pos as a four-element vector of the form [x y w h] in data
units. The x and y elements determine the location and the w and h
elements determine the size. The function plots into the current axes
without clearing existing content from the axes.
If you are just looking to increase the bounding box by some scale factor about the center of the rectangle, you could scale the w and h components in BB and adjust the rectangle origin x and y by subtracting half the scale difference. The following code should work if you place it right after the BB = step(FaceDetect,img); line in your code. I don't have MATLAB available to me at the moment but I'm pretty sure this will work.
% Scale the rectangle to 1.2 times its original size
scale = 1.2;
% Adjust the lower left corner of the rectangles
BB(:,1:2) = BB(:,1:2) - BB(:,3:4)*0.5*(scale - 1)
% Adjust the width and height of the rectangles
BB(:,3:4) = BB(:,3:4)*scale;
You can use imresize function in Matlab as described in this link and bboxresize to resize the bounding box
Below is the simple code to resize your image into 3 times the original one
%% clean workspace
clc;
clear;
cd 'C:\Users\abc\Desktop\folder';
files = dir('*.jpg');
for file = files'
img = imread(file.name) ;
figure(1),imshow(img);
FaceDetect = vision.CascadeObjectDetector;
FaceDetect.MergeThreshold =7;
BB = step(FaceDetect,img);
BB2 = BB;
%% Scale the rectangle to 3 times its original size
scale = 3;
%% Resize image
ImgResized = imresize(img,scale);
%% Resize bound box using the function named bboxresize in Matlab
BBResized = bboxresize(BB,scale);
figure(2),imshow(ImgResized);
%% Draw Bounding Box
for i=1:size(BBResized,1)
rectangle('position',BBResized(i,:),'lineWidth',2,'LineStyle','- ','EdgeColor','y');
end
end

code to define mask in matlab

I am working on developing a CBIR system, where I have to segment my RGB image in the following way:
I am implementing the code in matlab, but I am unable to build the proper masks for it.
I used imellipse but that requires the image handle which is achieved using imshow, but I don't want to show my image.
My code is
img=imread('peppers.png');
h_im=imshow(img); %I want to get rid of imshow because I don't want to show the image
[height, width, planes]=size(img);
%(cX,cY) is image center
cX=width/2;
cY=(height)/2;
%Here I define my ROI which is an ellipse that stretches to 75 percent of
%height and width of the image
e=imellipse(gca,[(1/2-3/8)*width, (1/2-3/8)*height,(3/4)*width,(3/4)*height]);
mymask=createMask(e,h_im);
%extending mask to three channels
mymask=repmat(mymask,[1 1 3]);
ROI=img;
ROI(mymask==0)=0;
figure, imshow(ROI);
You can generate the ellipse mask yourself rather than using the imellipse command.
% Create a meshgrid the same size of the image in order to generate the mask
[x y] = meshgrid(1:size(img, 1), 1:size(img, 2));
% Create the eclipse mask using the general form of an eclipse
% This will be centered in the middle of the image
% and have a height and width of 75% of th eimage
A = (0.75/2)*size(img, 2);
B = (0.75/2)*size(img, 1);
mask = A^2*(x - floor(size(img, 1)/2)).^2 + B^2*(y - floor(size(img, 2)/2)).^2<=A^2*B^2;
% Apply the eclipse mask
masked_image = img.*repmat(mask, [1, 1, 3]);
A bit of a hack but you could create a 'hidden' figure. The only difference is that I added: figure('Visible', 'off') at the start of your code.
figure('Visible', 'off');
img=imread('peppers.png');
h_im = imshow(img); %I want to get rid of imshow because I don't want to show the image
[height, width, planes]=size(img);
%(cX,cY) is image center
cX=width/2;
cY=(height)/2;
%Here I define my ROI which is an ellipse that stretches to 75 percent of
%height and width of the image
e=imellipse(gca,[(1/2-3/8)*width, (1/2-3/8)*height,(3/4)*width,(3/4)*height]);
mymask=createMask(e,h_im);
%extending mask to three channels
mymask=repmat(mymask,[1 1 3]);
ROI=img;
ROI(mymask==0)=0;
figure, imshow(ROI);
I think this code is easy to understand and easily adjustable to address an arbitrary part of your image (It has the same output as your code) :
img = imread('peppers.png');
% define the size of your ellipse relatively to the image dimension
factor = 0.75;
hwidth = size(img, 2) / 2.0;
hheight = size(img, 1) / 2.0;
a = hwidth * factor;
b = hheight * factor;
[x, y] = meshgrid(1:hwidth, 1:hheight);
% simple ellipse equation gets us part three of your mask
bottom_right_mask = (((x.^2)/a^2+(y.^2)/b^2)<=1);
% flip to get the remaining ones
top_right_mask = flipud(bottom_right_mask);
bottom_left_mask = fliplr(bottom_right_mask);
top_left_mask = flipud(bottom_left_mask);
mask = [top_left_mask, top_right_mask; ...
bottom_left_mask, bottom_right_mask];
multichannel_mask = repmat(mask,[1 1 3]);
ROI = img;
ROI(multichannel_mask==0) = 0;
figure;
imshow(ROI);

Background Image for Plot

Is there an easy way to put a bitmap image in the background of a Matlab plot which does not fill the whole available space und keeps its aspect ratio when the figure is resized?
TIA
I'm not quite sure to understand what you mean by
plot which does not fill the whole available space
however the following solution should help you solve your problem (or at least get you started).
Basically read an image (here grayscale) and display it using the imagesc command along with the grayscale colormap, then issue the hold on command and plot the data. Notice that you need to reverse the direction of the x-axis in order to get the right direction for the plot.
Here is the code:
clear
clc
close all
A = imread('cameraman.tif');
x = 1:10;
y = x;
figure
%// Notice the fliplr(A) to reverse the direction of the x data
imagesc([min(x(:)) max(x(:))], [min(y(:)) max(y(:))],fliplr(A));
colormap gray
%// Here reverse the direction of the x axis, otherwise the plot is
%// reversed
set(gca,'XDir','reverse')
hold on
plot(x,y,'--r')
axis off
And the result:
If your background image is RGB, you can use the image function: (modified from answer here): You need to flip the x data from the image for each channel separately, because fliplr only accepts 2D arguments:
DataXImage = linspace(min(x), max(x), size(A, 2));
DataYImage = linspace(min(y), max(y), size(A, 1));
%// flip dimensions for each channel
B = cat(3,fliplr(A(:,:,1)),fliplr(A(:,:,2)),fliplr(A(:,:,3)));
image(DataXImage, DataYImage, B, 'CDataMapping', 'scaled');
which, using the peppers.png image, gives this:
Is this what you had in mind? If not please tell me!
img = imread('myimage.png');
% set the range of the axes
% The image will be stretched to this.
min_x = 0;
max_x = 8;
min_y = 0;
max_y = 6;
% make data to plot - just a line.
x = min_x:max_x;
y = (6/8)*x;
imagesc([min_x max_x], [min_y max_y], img);
hold on;
plot(x,y);

plot circle with gradient gray scale color in matlab

I want to draw a circle with gradient color in matlab, but I can't. Is there any one that can help me?
the sample image can be found here
Here's one approach -
N = 200; %// this decides the size of image
[X,Y] = meshgrid(-1:1/N:1, -1:1/N:1) ;
nrm = sqrt(X.^2 + Y.^2);
out = uint8(255*(nrm/min(nrm(:,1)))); %// output image
figure, imshow(out) %// show image
Output -
If you would like to pad the output with white boundary as shown in the expect output image, you can do so with padarray -
padsize = 50; %// decides the boundary width
out = padarray(out,[padsize padsize],255);

Display images in different sizes in MATLAB

I am creating gaussian pyramid in MATLAB 2010b. I want to show images like same patterned mentioned here.
I tried to use imresize, truesize but getting all images in same size. Could anybody please help me on this issue?
You can use "imshow with True Size for multiple images" FEX file to answer your question...
EDIT : The code below will produce the subplot at the bottom right part of the figure:
clear imagesCellArray
mand = imread('mandelbrot_set.jpg'); % read image
dim = 3;
[imagesCellArray{1:dim,1:dim}] = deal(mand); % create smaller images by imresize
for iRow = 1:dim
for iCol = 1:dim
imagesCellArray{iRow,iCol} = imresize(imagesCellArray{iRow,iCol},1/(1.5*(iCol*iRow)));
end
end
% plot with imshowTruesize - true aspect ratio is preserved
margins = [25 25];
Handles = imshowTruesize(imagesCellArray,margins);
for iRow = 1:dim
for iCol = 1:dim
axis(Handles.hSubplot(iRow,iCol),'on')
end
end