Resizing image in matlab without using built in imresize() function - matlab

I am writing my own script/function in matlab without using built-in command, "imresize" but i am getting 3 output images instead of getting single one. I am sharing my code here also. Kindly someone spot out my mistake.
%zoomin out an imagge
originalImage = imread('imggerm1.jpg');
[origImRows, origImColumns] = size(originalImage);
newImage = zeros(origImRows/2, origImColumns/2);
newImRow = 1; newImColumn = 1;
for row = 1:2:origImRows
for column = 1:2:origImColumns
newImage(newImRow, newImColumn)=originalImage(row, column);
newImColumn = newImColumn+1;
end
newImRow = newImRow+1;
newImColumn = 1;
end
figure; imshow(originalImage);
figure; imshow(newImage/255);

This is because you originally reading a color image, where each pixel is encoded by 3 numbers. Try typing size(originalImage) and you will see that this array is 3 dimensional (the size of the last dimension is 3).
In your code the following line:
[origImRows, origImColumns] = size(originalImage);
Produces the result you don't expect: your origImColumns appears to be 3 times bigger.
Your code is easy to fix. Below I slightly changed 3 lines: #4, #6 and #11:
%zoomin out an imagge
originalImage = imread('1.jpg');
[origImRows, origImColumns,~] = size(originalImage);
newImage = zeros(origImRows/2, origImColumns/2,3);
newImRow = 1; newImColumn = 1;
for row = 1:2:origImRows
for column = 1:2:origImColumns
newImage(newImRow, newImColumn,:)=originalImage(row, column,:);
newImColumn = newImColumn+1;
end
newImRow = newImRow+1;
newImColumn = 1;
end
figure; imshow(originalImage);
figure; imshow(newImage/255);

Related

How to have image data stored defaultly inside Matlab GUI

I have an image attached as a logo for my GUI, currently, before OpeningFcn I am using imread to get the logo.
But I want to move my code between different computers and not planning to have the logo image along with the guide. Is it possible to define a function that creates the image I want?
Like,
imgData = createImg(); % function call
function imgData = createImg()
% imgData = imread('peppers.png'); % usual way
imgData = % idk do something to have it in this function definition.
end
Update: I followed what you said
imgData = imread('logo_Img.png');
csvwrite('imgDataLogical.txt',logical(imgData(:,:,1)));
function logical_idx = my_createImg()
% imgData = imread('peppers.png'); % usual way
logical_idx = [... % data...]; % data from txt file
end
logical_img = my_createImg();
[red_img,green_img,blue_img] = deal(uint8(255*(logical_img == 1)));
red_img(logical_img == 1) = 220; red_img(logical_img ~= 1) = 230;
green_img(logical_img == 1) = 20; green_img(logical_img ~= 1) = 230;
blue_img(logical_img == 1) = 60; blue_img(logical_img ~= 1) = 230;
fullImg = cat(3,red_img,green_img,blue_img);
figure, imshow(fullImg)
I think this is written pretty bad.
Any ideas to make it good.
Thanks,
Gopi
The easiest way to do this would be to copy-paste the data into the M-file.
Your M-file would look like this:
function imgData = createImg()
% imgData = imread('peppers.png'); % usual way
imgDataR = [...
43, 86, 43, 54, 123, 43, 132, ... (etc.)
];
imgDataG = [...
... (more data here)
];
imgDataB = [...
... (more data here)
];
imgData = cat(3, imgDataR, imgDataG, imgDataB);
end
To generate that data, read in the image and write it to text file using csvwrite:
imgData = imread('peppers.png');
csvwrite('imgDataR.txt',imgData(:,:,1));
csvwrite('imgDataG.txt',imgData(:,:,2));
csvwrite('imgDataB.txt',imgData(:,:,3));
And then open those text files and copy-paste the data to your M-file.
Though if you have a logo, you probably have few colors. It might be better to store it as an index matrix and a color map. But the principle would be the same.
To use a color map do as follows:
function logical_idx = my_createImg()
% imgData = imread('peppers.png'); % usual way
index = [... % data...]; % should have values 1 and 2
colmap = uint8([220,20,60; 230,230,230]);
imgData = colmap(index,:);
imgData = reshape(imgData,[size(index),3]);
end
Your index matrix should have values 1 and 2 (or higher numbers if you have more colors). To go from the logical matrix you have now to this, simply add 1. You use this matrix to index into the color map. You then need to reshape the output to have the correct sizes.

Background frame loop matlab

Im trying to make a loop for doing the same operation to a lot of .mov files in matlab. The code i have right now looks like this:
close all
clear all
clc
movFiles = dir('*.mov');
numFiles = length(movFiles);
mydata = cell(1,numFiles);
% mydata = zeros(numFiles);
for k = 1:numFiles
mydata{1,k} = VideoReader(movFiles(k).name);
end
for k=1:numFiles
bk_downsample = 5; %The downsample factor for frame averaging
%disp('Opening video...') %lower number =longer computation time
vob = mydata;
frame = vob.read(inf); %Reads to end = vob knows the number of frames
vidHeight = vob.Height;
vidWidth = vob.Width;
nFrames = vob.NumberOfFrames;
%% First-iteration background frame
background_frame = double(frame*0);
disp('Calculating background...')
for k = 1:bk_downsample:nFrames
background_frame = background_frame + double(read(vob, k));
disp(k/(nFrames)*100)
end
%background_frame = uint8(bk_downsample*background_frame/(nFrames));
background_frame = bk_downsample*background_frame/(nFrames);
%imshow(background_frame)
%% Second-iteration background frame
%This section re-calculates the background frame while attempting to
%minimize the effect of moving objects in the calculation
background_frame2 = double(frame*0);
pixel_sample_density = im2bw(double(frame*0));
diff_frame = double(frame*0);
stream_frame = diff_frame(:,:,1);
bk_downsample = 10;
figure
hold on
for k = 1:bk_downsample:nFrames
diff_frame = imabsdiff(double(read(vob, k)), background_frame);
diff_frame = 1-im2bw(uint8(diff_frame),.25);
pixel_sample_density = pixel_sample_density + diff_frame;
stream_frame = stream_frame + (1-diff_frame)/(nFrames/bk_downsample);
nonmoving = double(read(vob, k));
nonmoving(:,:,1) = nonmoving(:,:,1).*diff_frame;
nonmoving(:,:,2) = nonmoving(:,:,2).*diff_frame;
nonmoving(:,:,3) = nonmoving(:,:,3).*diff_frame;
background_frame2 = background_frame2 + nonmoving;
%pause
disp(k/(nFrames)*100)
end
background_frame2(:,:,1) = background_frame2(:,:,1)./pixel_sample_density;
background_frame2(:,:,2) = background_frame2(:,:,2)./pixel_sample_density;
background_frame2(:,:,3) = background_frame2(:,:,3)./pixel_sample_density;
imshow(uint8(background_frame2))
%imshow(stream_frame)
filename = ['Ring_' num2str(k) '_background_' num2str(img) '.jpg'];
imwrite((uint8(background_frame2)),filename)
end
I know that the error starts with vob=mydata; but im not sure how to correct it, hope that someone is able to help me since it would save me a lot of time in my data-analysis.
Have a great day! :)
Your code doesn't make much sense... You're creating a cell array:
mydata = cell(1,numFiles);
%// . . .
mydata{1,k} = . . .
but however you try to access it like a structure:
vob = mydata;
frame = vob.read(inf);
If I'd guess, then your error stems from you forgetting to index in the cell array, i.e.:
vob = mydata{k};
Other programming oddity I noticed in your code is the fact you're using the same looping variable k, in two nested for lops, the outer one being on k=1:numFiles and the inner ones being on k=1:bk_downsample:nFrames; don't do that unless you're trying to drive yourself crazy while figuring out why your for loop executes only once. Name them k1 for the outer loop and k2 for the inner loops and you'll be happier.
I'm no expert in video processing, but for me it looks like your line should be:
vob=mydata{1,k};
That's why that error shows up, because you are treating a cell of structs as if it was a single struct.

MATLAB combine two avi. together

I created two avi. file and they have the same length.
I wanted to combine them on a same background and one on top another one on the bottom.
The code I used for one of the animation is below, the other one is similar.
Is there any way I can do that?
load Results.mat;
I = imread('hex08.jpg');
[rows,columns,numberOfColorChannels] = size(I);
if numberOfColorChannels >1
I = I(:,:,2);
end
background = imresize(background, [rows,columns]);
figure(1);
hold on;
for i=1:500
A=angle(i,:);
J = imrotate(I,A,'crop');
mask = J == 0;
mask = bwareafilt(mask,4);
J(mask) = background(mask);
pause(0.01)
imshow(J);
imwrite(J,[num2str(i),'.png']);
end
imageNames = dir(fullfile('*.png'));
imageNames = {imageNames.name}';
outputVideo = VideoWriter(fullfile('hex08.avi'));
outputVideo.FrameRate = 15;
open(outputVideo)
for ii = 1:length(imageNames)
img = imread(fullfile(imageNames{ii}));
writeVideo(outputVideo,img)
end
close(outputVideo)
Here is one way this can be done:
Just like you read the image into img, you can read a second image (from the second video) into img2. Then, you can create a combined image of the two: imgCombined = [img ; img2]; which will contain the first image on top and the second on bottom (This will work if both images are the same width, otherwise you will need to resize/crop). When you write to the video file, use writeVideo(outputVideo,imgCombined).

How to convert rgb to gray but keep one colour unchanged

I have an image in which I want to only keep the green part and convert the others to gray scale.
It seems from the colors in your image, that the greens are actually so close to grayscale that you'll be unable to see anything. Either way this is how you do it:
im = imread('houses.jpg');
s= (im(:,:,2)>im(:,:,1))&(im(:,:,2)>im(:,:,3));
dim = double(im);
r = abs(dim(:,:,2)-((dim(:,:,1))+dim(:,:,2)+dim(:,:,3))/3) < 3;
q = s|r;
imgs = rgb2gray(im);
imgs3(:,:,1) = imgs;
imgs3(:,:,2) = imgs;
imgs3(:,:,3) = imgs;
imout = zeros(size(im));
for i=1:size(im,1),
for j=1:size(im,2),
if q(i,j) == 0,
imout(i,j,:) = imgs3(i,j,:);
else,
imout(i,j,:) = im(i,j,:);
end
end
end
imshow(uint8(imout))
imwrite(uint8(imout),'output.jpg');
if you want to see something useful you would probably want to do the following
im = imread('houses.jpg');
s= (im(:,:,2)>im(:,:,1))&(im(:,:,2)>im(:,:,3));
dim = double(im);
r = abs(dim(:,:,2)-((dim(:,:,1))+dim(:,:,2)+dim(:,:,3))/3) < 3;
q = s|r;
imgs = rgb2gray(im);
imgs3(:,:,1) = imgs;
imgs3(:,:,2) = imgs;
imgs3(:,:,3) = imgs;
imout = zeros(size(im));
for i=1:size(im,1),
for j=1:size(im,2),
if q(i,j) == 0,
imout(i,j,:) = imgs3(i,j,:);
else,
imout(i,j,1) = im(i,j,1);
imout(i,j,2) = 255;
imout(i,j,3) = im(i,j,3);
end
end
end
imshow(uint8(imout))
imwrite(uint8(imout),'output.jpg');
which gives this as result:
It should be something like this:
gray_img = rgb2gray(img);
green_mask = img(:,:,2) > img(:,:,1) & img(:,:,2) > img(:,:,3);
gray_img3 = cat(3, gray_img, gray_img, gray_img);
green_mask3 = cat(3, green_mask, green_mask, green_mask);
output_img = gray_img3;
output_img(green_mask3) = img(green_mask3);
I didn't check it, but I'm quite sure it should do the work.
The only thing you might want to modify is the computation of the mask, currently it will include all pixels that are more green than red or blue, but you may want to be more (or less) specific in choosing which pixels to leave unchanged.
I would suggest to use a purely hue=based approach, as you are interested in a specific color.
My approach would be to convert your images to the HSV colorspace and check the Hue channel.
img=imread('houses.jpg');
hsv=rgb2hsv(img);
% find the white areas of the image
gray_part=hsv(:,:,3)>0.7;
% find the green areas of the image that are not white
green_part=hsv(:,:,1)>(30/360) & hsv(:,:,1)<(210/360) & ~gray_part;
% create the output image
outimg=(uint8(double(img).*repmat(green_part,[1 1 3])));
figure;
subplot(121); imshow(img);
subplot(122); imshow(outimg);
This will give you the following image (left: original, right: resulting masked image):
Of course, if you need to get the rest of the image in grayscale you may use the previous results as follows:
pixel(1,1,1)=0;pixel(1,1,2)=255;pixel(1,1,3)=0;
green_img=repmat(pixel,[size(img,1) size(img,2), 1]);
green_part=repmat(green_part,[1 1 3]);
gray_img=rgb2gray(uint8(double(img).*~green_part));
gray_img=double(repmat(gray_img,[1 1 3]));
outimg=uint8(green_part.*green_img + gray_img);
figure; imshow(outimg);
This will display the image shown below:

N-th largest component of bwconncomp including the background

My question has two parts. First one is:
How can I include the background as a component in the bwconncomp function, because it's default behavior doesn't include it.
Also, and this is my other question is, how can I select the n-th largest component based on what I get by using bwconncomp.
Currently I was thinking about something like this, but that doesn't work :P
function out = getComponent(im,n)
CC = bwconncomp(im,4);
%image is an binary image here
numPixels = cellfun(#numel,CC.PixelIdxList);
sortedPixels = sort(numPixels,'descend');
w = sortedPixels(n);
[largest, index] = find(numPixels==w);
im(CC.PixelIdxList{index}) = 0;
out = im;
But that doesn't work at all. But im not too sure what the CC.PixelIdxList{index} does, is it just changing elements in the array. I also find it kinda vague what exactly PixelIdxList is.
To find the background, you can use 'not' operation on the image
'PixelIdxList' is not what you need. You need the 'Area' property.
function FindBackgroundAndLargestBlob
x = imread('peppers.png');
I = x(:,:,2);
level = graythresh(I);
bw = im2bw(I,level);
b = bwlabel(bw,8);
rp = regionprops(b,'Area','PixelIdxList');
areas = [rp.Area];
[unused,indexOfMax] = max(areas);
disp(indexOfMax);
end
Update:
You can do it with bwconncomp as well:
function FindBackgroundAndLargestBlob
x = imread('peppers.png');
I = x(:,:,2);
level = graythresh(I);
bw = im2bw(I,level);
c = bwconncomp(bw,4);
numOfPixels = cellfun(#numel,c.PixelIdxList);
[unused,indexOfMax] = max(numOfPixels);
figure;imshow(bw);
bw( c.PixelIdxList{indexOfMax} ) = 0;
figure;imshow(bw);
end
Which will give the following results: