fusing more than 2 images in matlab - matlab

In MATLAB, how do I fuse more than two images? For example, I want to do what imfuse does but for more than 2 images. Using two images, this is the code I have:
A = imread('file1.jpg');
B = imread('file2.jpg');
C = imfuse(A,B,'blend','Scaling','joint');
C will be fused version of A and B. I have about 50 images to fuse. How do I achieve this?

You could write a for loop, then simply have a single image that stores all of the fused results and repeatedly fusing this image with a new image you read in. As such, let's say your images were named from file1.jpg to file50.jpg. You could do something like this:
A = imread('file1.jpg');
for idx = 2 : 50
B = imread(['file' num2str(idx) '.jpg']); %// Read in the next image
A = imfuse(A, B, 'blend', 'Scaling', 'joint'); %// Fuse and store into A
end
What the above code will do is that it will repeatedly read in the next image, and fuse it with the image stored in A. At each iteration, it will take what is currently in A, fuse it with a new image, then store it back in A. That way, as we keep reading in images, we will keep fusing new images on top of those images that were fused from before. After this for loop finishes, you will have 50 images that are all fused together.

imfuse with the 'blend' method performs alpha blending on two images. In the absence of an alpha channel on the images, this is nothing more than the arithmetic mean of each pair of corresponding pixels. Therefore, one way of interpreting the fusion of N images is to simply average N corresponding pixels, one from each image, to get the output image.
Assuming that:
All images are of size imgSize (e.g., [480,640])
All images have the same pixel value range (e.g., 0-255 for uint8 or 0-1 for double)
the following should give you something reasonable:
numImages = 50;
A = zeros(imgSize,'double');
for idx = 1:numImages
% Borrowing rayryeng's nice filename construction
B = imread(['file' num2str(idx) '.jpg']);
A = A + double(B);
end
A = A/numImages;
The result will be in the array A with type double after the loop and may need to be cast back to the proper type for your image.

Piggy-backing on rayryeng's solution:
What you want to do is increase the alpha at every step in proportion to how much that image is contributing to the already stored images. For Example:
Adding 1 image to 1 existing image, you would want an alpha of 0.5 so that they are equal.
Now adding one image to the 2 existing images, it should contribute 33% to the image and therefore an alpha of 0.33. 4th image should contribute 25% (Alpha=0.25) and so on.
The result follows an x^-1 trend. So at the 20th image, 1/20 = 0.05, so an alpha of 0.05 would be necessary.

Related

How do I combining two or more images in Matlab?

I need to combine several images (of different textures) together. I have tried the following code:
% Read 4d data
I1 = importdata('Img1.tif');
I2 = importdata('Img2.tif');
% Extract a slice of the data
extractImg1 = I1(:,:,1);
extractImg2 = I2(:,:,1);
% compute image size
[ny1, nx1] = size(extractA1);
[ny2, nx2] = size(extractA2);
P1 = extractImg1 (round(ny1/2)-120:round(ny1/2)+120, round(nx1/2)-120:round(nx1/2)+120);
figure, imshow(P1); title('Img1');
P2 = extractImg2 (round(ny2/2)-120:round(ny2/2)+120, round(nx2/2)-120:round(nx2/2)+120);
figure, imshow(P2); title('Img2');
Please, what should I do next?
Secondly, the combined image will be needed for laser printing. The images do not have exactly the same pixel dimensions thus; I was told that it would not make sense to combine them, as this might slightly reduce accuracy.
Nonetheless, I still have a feeling that combining the images wouldn’t be wrong considering that they all have the same resolutions.
I need advice as to whether I should go ahead with the combination. Many thanks in advance.
You have extracted two equal-sized regions from the two images. If you want to put those side-by-side in the same image, use cat, or equivalently, use the square brackets []:
next_to_each_other = [P1,P2];
on_top_of_each_other = [P1;P2];
But note that you can put these things together even if they don't have the same sizes. For example, if I1 is NxM pixels, and I2 is NxK (with N the vertical size as customary in MATLAB) then you can still do [I1,I2] because the vertical size matches.
If nether the vertical nor horizontal sizes match, you can pad one with zeros (or whatever value is appropriate) using padarray before putting them together:
ny1 = size(I1,1);
ny2 = size(I2,1);
if ny1<ny2
I1 = padarray(I1,[ny2-ny1,0,0],0,'post'); % The 0 is the value to pad
elseif ny2<ny1
I2 = padarray(I2,[ny1-ny2,0,0],0,'post'); % The 0 is the value to pad
end
out = [I1,I2];
padarray also allows replicating the data in the matrix instead of padding with zeros. Read the documentation to find what is appropriate. padarray requires the Image Processing Toolbox. If you don't have it, you can replicate its functionality by creating an array with zeros of the appropriate size using the zeros function, and adding it to the image using something like [I1;zeros(ny2-ny1,size(I1,2),size(I1,3)].

Superimposing Multiple Images + Adding Colormap

I'm an undergrad student working in a cell biology lab with a basic background in matlab. I'm working on a project of tracking cell trajectory (time lapse) on a petri dish. Below are two example images that i used the watershed feature to separate from the background. The original pictures had neon green cells, now this is all in black and white/
Let's say i have 20 pictures like this, how might I superimpose one on top of another so they all of equal transparency?
Then, how can i add a colormap that represents time? (The bottom most picture is one end of the colormap and the most recent picture is the opposite end) <- this is extremely challenging as it often things the background is black and not NaN
The Basic Idea
Probably the easiest way to do this, is to take the binary image for each layer, and multiply the image by the time at which it was acquired (or it's index in time). Then you can concatenate all images along the third dimension (using cat). You can compute the maximum value along the third dimension using max. This will make the newer time points appear to be "on top" of the older time points. You can then display the resulting flattened matrix using imagesc and it will automatically map to the colormap for the current figure. Typically we would refer to this as a maximum intensity projection.
Creating Some Data
First since you've only provided two images, I'm going to create some shifted versions of the first image you've provided for the demonstration.
% Create some pseudo-data in a cell array that represents the image over time
im = imread('http://i.imgur.com/xTurvfO.jpg');
im = im(:,:,1);
ims = cell(1, 5);
% Create some shifted versions of im1
shifts = round(linspace(0,1000,5));
for k = 1:numel(shifts)
ims{k} = circshift(im > 100, shifts([k k]));
end
Implementing the Method
Now for the application of the method I discussed
% For each image, multiply the binary mask by the time
for k = 1:numel(ims)
ims{k} = ims{k} * k;
end
% Concatenate all images along the third dimension
IMS = cat(3, ims{:});
% Flatten by taking the maximum value along the third dimension
MIP = max(IMS, [], 3);
% Display the resulting flattened image using imagesc
imagesc(MIP);
% Create a custom colormap with black at the end to create our black background
colormap(cat(1, [0 0 0], parula))
The Result
I have used imfuse to create composite images, which is similar to combining multiple channels on a fluorescent microscope. The Mathworks documentation is http://www.mathworks.com/help/images/ref/imfuse.html.
The tricky part is choosing the vector for color channels. For example, [2,1,2] means choosing B(lue) for image 1, R(ed) and G(reen) for image 2. [2,1,2] is the scheme recommended for colorblind people and gives figure on the left of this image. Using [1,0,2] for red/blue gives the the figure on the right.
fig1 = imread([basepath filesep 'fig.jpg']); %white --> black
fig2 = imread([basepath filesep 'fig2.jpg']);
fig_overlay = imfuse(fig1, fig2,'falsecolor','Scaling','joint', 'ColorChannels', [1,0,2]);
imshow(fig_overlay)

Matlab : How to check if two images are similar to each other

I have coloured images of size 20 by 20. The objective is that :
based on a query, I need to check which recalled image is the closest match to the query. For example, let 10 images be the recalled ones. Out of the 10 recalled images, I need to find the closest match to the query.
I was thinking of using the correlation between the images. One can use the Correlation coefficient - higher the value, more is the correlation between pixel values. (Please correct me where wrong).
R = corr2(A,B1) will compute the correlation coefficient between A and B where A is the query, B1 is the first recalled image image of the same size. I used the above command for colored images but I got the result R = NaN. How do I solve this problem for colored and gray scale. Thank you.
This is the QUERY IMAGE
The other image(recalled / retrieved B1)
UPDATE : Code for testing correlation of an image with itself from a databasae called patches.mat (patches is the database. It consists of 59500 20x20 patches, reshaped into 400-dimensional column vectors,
taken from a bunch of motorcycle images; I am using the 50 th example as the query image)
img_query = imagesc(reshape(patches(:,50),20,20));
colormap gray;axis image;
R = corr2(img_query,img_query)
Answer = NaN
That is because one of the images is black or includes a single color, meaning that all the values of the matrix are similar. Check the following examples:
I = imread('pout.tif');
J = I*0; % create a black image
R = corr2(I,J);
R =
NaN
I = imread('pout.tif');
J = 255*ones(size(I)); % create a white image
R = corr2(I,J);
R =
NaN
Update
It should work in your case, as you can see in the following example, it works perfectly:
I1 = abs(255*(rand(10,10));
I2 = abs(255*(rand(10,10));
corr2(I1,I2)
ans =
0.0713
Even with the images you have shared, it is working for me. To find out your problem, you have to either share a part of your code, or post images as they are, not saved images (with a size 420x560x3).
Note: you cannot have images including more than 1 layer.
Your code shows that you are using the handle of the image instead of the image itself.
Test this:
I = reshape(patches(:,50),20,20);
corr2(I,I)
I would try also the Universal Quality Index by Wang which gives you a 1.0 if both images are equal, and less in other cases with spatial indication where they differ, think of one image as reference, the other as a degraded one relative to the first one. See http://www.cns.nyu.edu/~zwang/files/research/quality_index/demo.html

comparing images pixel by pixel

I am working on some images. I am given an abc.tif image ( color image) . I read it as follows:
Mat test_image=imread("abc.tif",IMREAD_UNCHANGED);
I perform some operations on it and convert it into some binary image (using threshold) containing only two values 0 and 255 which are stored in img image where img is created as following:
Mat img(584,565,CV_8UC1); %//(so now img contains only 0 and 255)
I save this image using imwrite("myimage.jpg",img);
I want to compare the myimage.jpg image with another binary image manual.gif pixel by pixel to check whether one image is duplicate of another but as you can notice the problem is OpenCv doesnot support .gif format so I need to convert it into .jpg and because of that the image changes and now both the images will be concluded as different images may be even though they are same. What to do now?
Actually I am working on retinal blood vessel segmentation and these images are found in the DRIVE database.
I am given these images. Original image:
I perform some operations on it and extract blood vessels from it and then create a binary image and store in some Mat variable img as discussed earlier. Now I have got another image (.gif image) which I cannot load as shown below:
Now I want to compare my img image (binary) with the given .gif image (above) which I cannot load.
Use ImageMagic for converting your .gif to .PNG in batch mode. You could also convert it on the fly using system("convert img.gif img.png") call.
I'm not sure, if pixel comparison will give you good result. An offset shift of the same image will result in bad match.
EDIT As an idea. Maybe calculating centers of gravity and shifting/rotating both images to have the same origin may help here.
Consider using moments, freeman chain or other mode robust shape comparison methods.
first off you will want to use the images in the same format as each other #Adi mentioned jpg is lossy in the comments which is correct so shouldn't be used until possibly after any work is done. MATLAB - image conversion
you will also want the images to be of the same size. you can compare them using the size function and then pad them to add pixels to make the dimensions the same. the padding can always be removed later, just watch how the padding is added so as not to affect your operations.
you will also need to look into rotations, consider putting the image into the frequency domain and rotate the image to align the spectrum's.
below is a simple pixel comparison code, pixel comparison is not particularly accurate for comparing. even the slightest miss alignment will cause false negatives or false positives.
%read image
test_image1 = imread('C:\Users\Public\Pictures\Sample Pictures\Desert.jpg');
test_image2 = imread('C:\Users\Public\Pictures\Sample Pictures\Hydrangeas.jpg');
%convert to gray scale
gray_img1 = rgb2gray(test_image1);
gray_img2 = rgb2gray(test_image2);
% threshold image to put all values greater than 125 to 255 and all values
% below 125 to 0
binary_image1 = gray_img1 > 125;
binary_image2 = gray_img2 > 125;
%binary image to size to allow pixel by pixel checking
[row, col] = size(binary_image1);
% initialize the counters for similar and different pixelse to zero
similar = 0;
different = 0;
%two loops to scan through all rows and columns of the image.
for kk = 1 : row
for yy = 1 : col
%using if statement with isequal function to compare corresponding
%pixel values and count them depending ont he logical output of
%isequal
if isequal(binary_image1(kk,yy), binary_image2(kk,yy))
similar = similar + 1;
else
different = different + 1;
end
end
end
% calculate the percentage difference between the images and print it
total_pixels = row*col;
difference_percentage = (different / total_pixels) * 100;
fprintf('%f%% difference between the compared images \n%d pixels being different to %d total pixels\n', difference_percentage, different, total_pixels )
% simple supbtraction of the two images
diff_image = binary_image1 - binary_image2;
%generate figure to show the original gray and corresponding binary images
%as well as the subtraction
figure
subplot(2,3,1)
imshow(gray_img1);
title('gray img1');
subplot(2,3,2)
imshow(gray_img2);
title('gray img2');
subplot(2,3,4)
imshow(binary_image1);
title('binary image1');
subplot(2,3,5)
imshow(binary_image2);
title('binary image2');
subplot(2,3,[3,6])
imshow(diff_image);
title('diff image');

Extract images from video, change them to grayscale and find the differences

I am writing a function which takes the following actions: extracting from video, convert the frames to grayscale and calculate the difference between first two images that i have extract.
I have done the code up to this point. But I have no idea how to extract the images that were extracted previously. Can anyone provide some guidance on this?
function [ vid ] = motion( input_args )
vid = (input_args);
readerobj = VideoReader(vid);
vidFrames = read(readerobj);
numFrames = get(readerobj, 'Number of Frames');
for k = 1 : numFrames
mov(k).cdata = vidFrames(:,:,:,k);
mov(k).colormap = [];
imagename=strcat(int2str(k), '.jpg');
%save inside output folder
imwrite(mov(k).cdata, strcat('output\frame-',imagename));
end
end
Reading your problem description, you want to do a difference of frames (in grayscale) between the previous frame and the current frame. What you can do is store the first frame as a temporary variable, then in your for loop, you would take the difference between the current frame and the previous frame. Before you iterate to the next frame, be sure to set this current frame as the previous frame, and then proceed. Obviously, you need to create the grayscale equivalent of each frame you have read in. As such, you should change your for loop to this:
prevFrame = rgb2gray(vidFrames(:,:,:,1)); %// Initialize and get grayscale
for k = 2 : numFrames %// Note we start at index 2
currFrame = rgb2gray(vidFrames(:,:,:,k)); %// Get current frame
%// and get grayscale
%// Find difference frame
diffFrame = uint8(abs(double(currFrame) - double(prevFrame)));
mov(k).cdata = cat(3,diffFrame,diffFrame,diffFrame); %// Now save to file
mov(k).colormap = [];
imagename=strcat(int2str(k), '.jpg');
%//save inside output folder
imwrite(mov(k).cdata, strcat('output\frame-',imagename));
prevFrame = currFrame; %// Save for next iteration
end
Pay special attention to how I calculated the difference frame. I casted each of the frames to double, then took the absolute difference, then recast it as uint8. The reason why is because if you don't do this, if there are any pixels that have a negative difference, MATLAB will saturate this difference to 0. For example, if one pixel was intensity 128 in one frame, then 255 in the next, the difference should be -127. We put an abs here because this is really a difference of 127. It doesn't matter which direction we are going in. However, MATLAB will consider this difference as 0 as anything that is less than 0 gets saturated to 0. As such, I need to convert both frames to double as the frames you read in from file will most likely be uint8. Once you find the absolute difference, we then recast as uint8 so we can save to file and also be able to display these images if desired.
Now the code will save the difference images to file. Note that you will be one frame short because we started at frame 2. This is necessary if you want to compare differences between consecutive frames. Note that when you are creating your frame, I had to replicate the difference frame and make it three channels to mimic a RGB frame. For a grayscale image, the RGB will have each channel to be all the same. This was done using the cat command, and I stacked the difference frame in the third dimension three times.
What's good about your mov structure now is that you can use this structure and create a video out of it using MATLAB's VideoWriter class for example. The structure is exactly formatted to be written to file. Simply loop through your stucture and write each structure element to file with the VideoWriter class. You'll then be able to produce a movie that shows the difference between consecutive frames.