I'm trying to write a function in matlab for averaging images (all of the same size and format (.png)). But it's not really working at the moment. The error i get is: "Error using +, Integers can only be combined with integers of the same class, or scalar doubles."
The code is below. The images are all resized to the same size, and have padding applied if the proportions aren't equal (padding is done with an alpha channel, to make the padding transparent). The images are all proper png's, and can be opened in photoshop etc. without errors.
If i understand correctly, you don't have to initialize or declare variables in matlab. Which is probably part of my problem. My normal (processing/java) approach would be to initialize containerAv to be of size (x, y, 3), add all the color values of all images to it, and then divide all values by the number of images. Giving you the average image.
I don't really know how to do this in matlab. What am i doing wrong? How do i rewrite this code so it gets me the rgb average image?
function imageCentroid(imageList, resizeFolder, outputFolder, x, y)
% local variable
centroidImage = zeros([x y 3]);
% loop through all images in the resizeFolder
for i=1:length(imageList)
% get filename and load image
fname = imageList(i).name;
container = imread([resizeFolder fname]);
% add container values to centroidImage
centroidImage = centroidImage + container;
end
% calculate mean image (divide by number of images)
centroidImage = centroidImage / length(imageList);
% save mean image
imwrite(centroidImage, [outputFolder 'centroid.png']);
end
Probably change:
container = imread([resizeFolder fname]);
to
container = im2double(imread([resizeFolder fname]));
Related
I need to merge multiple bitmap of same sizes into one image.That image is basically rotated in different angles and needs to be merged into one whole image. I have tried multiple methods but I come with many issues as I am not able to save that image.
I have tried multiple codes but I actually cannot make sense out of it. What I want to achieve is transparent overlay (not sure) that superimposes two images and you can actually see both one image
figure1 = figure;
ax1 = axes('Parent',figure1);
ax2 = axes('Parent',figure1);
set(ax1,'Visible','off');
set(ax2,'Visible','off');
[a,map,alpha] = imread('E:\training data\0.bmp');
I = imshow(a,'Parent',ax2);
set(I,'AlphaData',alpha);
F = imshow('E:\training data\200.bmp','Parent',ax1);
I just want to superimpose multiple images.
This is my data set:
This is what I want to achieve, i want to add all of the rotated images and achieved into one
This is what I get sadly, I have tried everything
The following does kind of what you want. First load the image, then divide it into 6 equal blocks, and add these. To add the pixel values, I first converted the image to doubles, since uint8 only can go up to pixel values of 255. This would mean that you will just see a large bright spot in the image because you are clipping.
Then add all the blocks. You will see in the output, that the car is not always perfect in the center of the block, so depending on what you are trying to achieve you may want to align the blocks using something like xcorr2.
% load image
A = imread('S82CW.jpg');
fig = figure(1); clf
image(A);
% convert A to double and divide in blocks.
A = double(A);
[img_h, img_w, ~] = size(A);
block_h = img_h/2;
block_w = img_w/3;
% split image in blocks
Asplit = mat2cell(A, repelem(block_h,2), repelem(block_w,3), 3);
% check if splitting makes sense
figure(2); clf
for k = 1:numel(Asplit)
subplot(3,2,k)
image(uint8(Asplit{k}))
end
% superimpose all blocks,
A_super = zeros(size(Asplit{1,1}),'like',Asplit{1,1} ); % init array, make sure same datatype
for k = 1:numel(Asplit)
A_super = A_super + Asplit{k};
end
% divide by max value in A and multiply by 255 to make pixel
% values fit in uint8 (0-255)
A_super_unit8 = uint8(A_super/max(A_super,[],'all')*255);
figure(3); clf;
image(A_super_unit8)
As the title says, the output I’m getting out of this function is incorrect. By incorrect I mean that the data are overflowing. How do I normalise the matrix correctly? Currently almost all of the pictures I get are white.
I called the function from another MATLAB file like this:
mask = [3,10,3;0,0,0;-3,-10,-3];
A = imread(“football.jpg”);
B = ConvFun(A,mask);
function [ image ] = ConvFun( img,matrix )
[rows,cols] = size(img); %// Change
%// New - Create a padded matrix that is the same class as the input
new_img = zeros(rows+2,cols+2);
new_img = cast(new_img, class(img));
%// New - Place original image in padded result
new_img(2:end-1,2:end-1) = img;
%// Also create new output image the same size as the padded result
image = zeros(size(new_img));
image = cast(image, class(img));
for i=2:1:rows+1 %// Change
for j=2:1:cols+1 %// Change
value=0;
for g=-1:1:1
for l=-1:1:1
value=value+new_img(i+g,j+l)*matrix(g+2,l+2); %// Change
end
end
image(i,j)=value;
end
end
%// Change
%// Crop the image and remove the extra border pixels
image = image(2:end-1,2:end-1);
imshow(image)
end
In a convolution, if you want the pixel value to stay in the same range
, you need to make the mask add up to 1. Just divide the mask by sum(mask(:)) after defining it. This is however, not the case you are dealing with.
Sometimes that is not the needed. For example if you are doing edge detection (like the kernel you show), you don't really care about maintaining the pixel values. In those cases, the plotting of unnormalized images is more the problem. You can always set the imshow function to auto select display range: imshow(image,[]).
Also, I hope this is homework, as this is the absolutely worst way to code convolution. FFT based convolution is about 100 times faster generally, and MATLAB has an inbuilt for it.
I need a little help guys in Matlab in Matrix Dimensions,
I Have two images imported by imread function:
im1 = imread('1.jpg');
im2 = imread('2.jpg');
im1 is the reference image, while im2 is the Noisy image.
In the workspace window, Matlab shows the im2 Dimensions like this: 768x1024x3
while im2 displayed as: 768x1024
They are both RGB, there's no greyscale images,
In fact the second image is the a compressed image (performed compression algorithm on it ) while the first image is natural JPEG Image, untouched
and for calculating MSE/PNSR for both images, the matrix dimensions must be the same.
I Will need to transform im1 dimensions to be 3d like the first image (768x1024)
I tried this functions (squeeze, reshape) and with no success
You were on the right track with repmat. Here's the correct syntax:
im2 = repmat(im2, [1 1 3]);
This says you want 1 replicate along the first dimension, 1 replicate along the second dimension, and 3 replicates along the third dimension.
Are you sure that both are RGB images because im2 has only one channel and it looks grayscale but it can also be a colormap image in that case try
[im2, map] = imread('im2.jpg');
and see if anything is appearing in map variable. If the image is indeed colormap image, the map variable should be of size 256 X 3.
What donda has suggested is repeating the grayscale channel 3 times to make it of size 768x1024x3. Another possibility is that noisy image was created by converting RGB image to grayscale or by taking green channel of RGB image. Verify the source of the image in that case.
About PSNR computation I have a feeling that there is some problem with your code. I have given my code below use this and see if it works. Get back to me if you face any problem.
function [Psnr_DB] = psnr(I,I_out)
I = double(I);
I_out = double(I_out);
total_error = 0;
for iterz = 1:size(I,3)
for iterx = 1:size(I,1)
for itery = 1:size(I,2)
total_error = total_error + (I(iterx,itery,iterz)-I_out(iterx,itery,iterz))^2;
end
end
end
MSE = total_error/numel(I);
Psnr = (255^2)/MSE;
Psnr_DB = 10*log10(Psnr) %#ok<NOPRT>
I am trying to sum up all the values in a 400 x 640 image that are within a masked region using the roifilt2 function. I created a mask using roipoly and it is also stored as a 400 x 640 matrix with 0's in the cells I am uninterested in and 1's in the cells that I wish to sum up.
I was wondering how you would go about this, I have looked at the mathworks page for roifilt2 but I don't understand how to pass the sum function into this properly. This is what I'm trying:
fh = #(I)(sum(I,2));
I2 = roifilt2(I, mask, fh);
where I is my image and mask is my mask. I also keep getting the following error, even though my I and my mask are DEFINITELY the same size:
Error using roifilt2 (line 79)
The filtered image is not the same size as the original image.
Any help would be appreciated, Thanks!
The problem is that the sum changes the size of the output image, try by clearing all the values outside of the region then summing up
% Define the function you want to use as a filter.
% This function, named f, passes the input image x to the imsharpen
% function and specifies the strength of the sharpening effect
% by using the 'Amount' name-value pair argument.
% f simply puts the values to 0
f = #(x)x-x;
% Filter the ROI using the roifilt2 function and specifying the image, mask, and filtering function.
% This filter clears all the values which are not in the region of interest
interest_region = roifilt2(img, ~mask, f);
So the final sum of the values in your region will be:
img_sum = sum(interest_region,'all');
Anyway, as Raab70 wrote, you could multiply by the mask to obtain the same result without using roifilt2:
img_sum = sum(img.*mask,'all');
How to do this on matlab?
zero pad the face image with a five‐pixel
thick rim around the borders of the
image. show the resulting image.
Must be manual codes on script.
save this function as create_padded_image.m
function padded_image = create_padded_image(image, padding)
if nargin < 2
% if no padding passed - define it.
padding = 5;
end
if nargin < 1
% let's create an image if none is given
image = rand(5, 4)
end
% what are the image dimensions?
image_size = size(image);
% allocate zero array of new padded image
padded_image = zeros(2*padding + image_size(1), 2*padding + image_size(2))
% write image into the center of padded image
padded_image(padding+1:padding+image_size(1), padding+1:padding+image_size(2)) = image;
end
Then call it like this:
% read in image - assuming that your image is a grayscale image
$ image = imread(filename);
$ padded_image = create_padded_image(image)
This sounds like homework, so I will just give you a hint:
In MATLAB it is very easy to put the content of one matrix into another at precisely the correct place. Check out the help for matrix indexing and you should be able to solve it.
I realize you want to code this yourself, but for reference, you can use the PADARRAY function. Example:
I = imread('coins.png');
II = padarray(I,[5 5],0,'both');
imshow(II)
Note this works also for multidimensional matrices (RGB images for example)