I've a 3D vector holding images in Matlab, its 480x640x1400. I want to loop through the 1400 images. For I want to get the median of the first 10 images (from 1-->10) and save it as a one 480x640 image then get the images from 2-->11 and get the median and save it as another image and so on (3-->12)....
So for example:
images is the 3D vector holding images with size 480x640x1400
images2 is the required 3D vector holding the median of the images with size 480x640x1400.
This is the script I'm using:
l=dir('*.mat');
filenames={l.name}';
nfiles=length(filenames)
idx=1;
strtidx=1;
endidx=nfiles;
step=1;
waitbar(0);
for i=strtidx:step:1
tmp = load(filenames{i},'images');
idx=1;
for j=strtidx:step:1000
for k=j:step:j+9
tmp2(k)=tmp(:,:,k);
end
mm=median(tmp2,3);
images2(j)=mm;
end
save(filenames{i}, 'images2', '-append');
waitbar(i/nfiles);
close all;
end
Assuming you have a matrix with the dimensions you described called Images. Firstly it could be a normal matrix of images, or a cell matrix. Are these colour images? Secondly you only have 1400 images, not 1401, Matlab indexes from 1 not from 0.
If it is a normal array of single channel images (i.e. greyscale) then you want this:
for imageNumber = 1:size(Images,3)-9 %loop along the third dimension
NewImages(:, :, imageNumber) = findMedian(Images(:,:,imageNumber:imageNumber + 9)) %findMedian is your own function that you must write that outputs the median of 10 images as a 480 x 640 matrix.
end
Related
My goal is to create a heatmap in Matlab using an existing floor plan, and manually collected RF RSSI values.
I have marked numerical values (~30 to ~80) on a floor plan using pen and paper after recording signal strength in various areas of a building. I am looking to plot this in a heatmap overlay to the original floor plan.
What I have done is the following:
Google. YouTube. Man pages. My research has landed me accomplishing the following:
Importing an image to Matlab by asking the user to select a photo
Write it to the imread() function
Set an array the size of the image, all zeroed out
This is currently done manually, but not a concern right now
Manually placing, heatmap(x,y) = val; in locations marked on the original plan
I have found the x,y pixel coordinates from Photoshops info pallet
used a Gaussian low pass filter on the points set by heatmap()
The filter argument includes the image dimensions in pixels
At this point, I try to display the filtered heatmap()-ed points over the original floor plan. I am using the same dimensions for the filtering and the array made from the image size, in pixels. However, I am not getting the heatmap points to overlay where I specified by hard coding it.
The code is as follows:
%Import an image***********************************************
%Ask a user to import the image they want
%**************************************************************
%The commented out line will not show the file type when prompted to select
%an image
%[fn,pn] = uigetfile({'*.TIFF,*.jpg,*.JPG,*.jpeg,*.bmp','Image files'}, 'Select an image');
%This line will select any file type, want to restrict in future
[fn,pn] = uigetfile({'*.*','Image files'}, 'Select an image');
importedImage = imread(fullfile(pn,fn));
%Create size for heat map**************************************
%Setting the size for the map, see comments below
%**************************************************************
%What if I wanted an arbitrary dimension
%Or better yet, get the dimensions from the imported file
heatMap = zeros(1512,1080);
%Manually placing the heatmap values along a grid
%Want to set zones for this, maybe plot out in excel and use the cells to
%define the image size?
heatMap(328,84) = .38;
heatMap(385,132) = .42;
heatMap(418,86) = .40;
heatMap(340,405) = .60;
heatMap(515,263) = .35;
heatMap(627,480) = .40;
heatMap(800,673) = .28;
heatMap(892,598) = .38;
heatMap(1020,540) = .33;
heatMap(1145,684) = .38;
heatMap(912,275) = .44;
heatMap(798,185) = .54;
%Generate the Map**********************************************
%Making the density and heat map
%**************************************************************
gaussiankernel = fspecial('gaussian', [1512 1080], 60);
density = imfilter(heatMap, gaussiankernel, 'replicate');
%imshow(density, []);
oMask = heatmap_overlay(importedImage, density, 'summer');
set(figure(1), 'Position', [0 0 1512 1080]);
imshow(oMask,[]);
colormap(summer);
colorbar;
Any idea why the overlayed filter is offset and not where specified?
This can be reproduced by any image 1512 x 1080
Please let me know if you want the original image used
The array was off.
What I did was the following:
Output the density map only
Verified dimension sizes in the Matlab Workspace
I have noticed the array for the density, heatMap, importedImage and oMask were not all n x m size.
heatMap and importedImage were n x m, and importedImage and oMask were m x n.
I swapped the dimensions to all be n x m and now the image overlays just fine.
I have 2D matrixs of dimensions 400 x 500,each of these matrixs show an image. my process contain 2 steps:
1) I have to partition these images (split matrix to equal sized sub-matrices)
2) I have to save each of these split in one matrix
first step is done and dimention of matrix change from 2D-->3D (the last index shows index of splits)
now for the step 2 I have 100 images and I want to have matrix with 4 dimensions which the last index show the number of images
sample : for accessing split 3 of image 40 : [:,:,3,40]
I already try to using permut and reshape but not successful
here is my code
nCol = 10;
nRow = 4;
K=dir(p);
Len=length(K);
for i=3:Len
x1=imread(strcat(p,'\',K(i).name));
[m,n,d1]=size(x1);
if d1==1
x=double(x1);
else
x=double(rgb2gray(x1));
end
x=imresize(x,NN);
%% determined width and height of divided matrix %%%%%%%%%%%%%%%%%%%%%%%%%%
m = size(x,1)/nRow;
n = size(x,2)/nCol;
T = permute(reshape(permute(reshape(x, size(x, 1), n, []), [2 1 3]), n, m, []), [2 1 3]);
Im=[Im T(:,:,:,i-2)];
end
any idea would be appreciated.
reshape picks elements in column major ordering so you might have to write convoluted code to get it to work. Rather than going the way of using permute and reshape to create 4D matrices and potentially running into an out of memory issue I would advice the use of mat2cell to split your matrix into a cell array because mat2cell splits a matrix like you would want to split an image.
Here I show an example with an image
RGB = imread('peppers.png');
x = rgb2gray(RGB); % x is a 384 x 512 matrix, we want to split in 3 rows and 2 columns
x2 = mat2cell(x,384*ones(3,1)/3,512*ones(2,1)/2); % 2D cell array, each cell holds a part of the image
imshow(x2{1,1}) % Top left part of the image
You could loop over all your images and create a 3D cell array where each layer in the array represents each image split into pieces. I would suggest to preallocate you array and assign the matrix in the correct layer within the loop rather than incrementally increasing the size of your matrix.
Also there seems to be an Image processing toolbox specific function to do what you are trying to : Check this : How to divide an image into blocks in MATLAB?
I've been using blockproc for processing images blockwise. Unfortunately, blockproc is part of the Image Processing Toolbox, which I don't have on my personal computer.
Is there a combination of functions in base Matlab that can substitute for blockproc?
My initial guess was to use im2col to transform each block into columns, and then arrayfun to process each column. Then I realized that im2col is also a part of the Image Processing Toolbox, so that doesn't solve my problem.
Here is an example using MAT2CELL. It dividing the image into N-by-M tiles, and handles the case when the image size is not evenly divisible by the number of tiles.
%# 2D grayscale image
I = imread('coins.png');
%# desird number of horizontal/vertical tiles to divide the image into
numBlkH = 4;
numBlkW = 4;
%# compute size of each tile in pixels
[imgH,imgW,~] = size(I);
szBlkH = [repmat(fix(imgH/numBlkH),1,numBlkH-1) imgH-fix(imgH/numBlkH)*(numBlkH-1)];
szBlkW = [repmat(fix(imgW/numBlkW),1,numBlkW-1) imgW-fix(imgW/numBlkW)*(numBlkW-1)];
%# divide into tiles, and linearize using a row-major order
C = mat2cell(I, szBlkH, szBlkW)';
C = C(:);
%# display tiles i subplots
figure, imshow(I)
figure
for i=1:numBlkH*numBlkW
subplot(numBlkH,numBlkW,i), imshow( C{i} )
end
The input image and the resulting tiles:
Won't mat2tiles together with cellfun and cell2mat do more or less what blockproc does?
You could write a wrapper yourself to make it use the same arguments as blockproc, I don't think it should be that hard to do.
The mat file is a 156*192*25 3D matrix. The data are a series of n=25 images in a mat file. How could I convert this 3D matrix into 25 2D matrix and display them independently? Thanks~
I recommend not to split your stack of images, instead simply use I(:,:,3) if you for example need the third image.
To display the images you can use:
montage(permute(I,[1,2,4,3]))
To display all images together. The permute is required because montage expects a 156*192*1*25 for stacked grey scale images, the third dimension is reserved for colour channels. Alternatively to display an individual image use:
imshow(I(:,:,3));
To save each image to an individual mat file use:
for ix=1:size(I,3)
M=matfile(sprintf('image%03d',ix),'writable',true);
M.image=I(:,:,ix);
end
Using the mat2cell command, you could convert the 3D value matrix to a array of 25 cells, where each cell holds a 156x192 2D value matrix:
M = rand(156,192,25); %// simulate your 3D data matrix
Mcell = mat2cell(M,156,192,ones(1,25));
Alternatively, using arrayfun command:
Mcell = arrayfun(#(x) M(:,:,x), 1:25, 'UniformOutput', false)
You can now access the 25 images one by one as:
imageNum = 5; %// example: access image num. 5
image = Mcell{imageNum}; %// image: 156x192 value matrix
One benefit of keeping the images in a cell array is that you can easily apply e.g. the same filter to all images, making use of the cellfun command, e.g.:
h = fspecial('motion', 50, 45);
McellFiltered = cellfun(#(x) imfilter(x, h), Mcell, ...
'UniformOutput', false);
i have 100 b&w image of smthing.the probllem is i want to scan each image in 0&1 formatin mby n format and then place each image to one over one and again scan and save them in mbynby100 form.
how i do this and from where i should start
_jaysean
Your question is vague and hard to understand, but my guess is that you want to take 100 M-by-N grayscale intensity images, threshold them to create logical matrices (i.e. containing zeroes and ones), then put them together into one M-by-N-by-100 matrix. You can do the thresholding by simply picking a threshold value yourself, like 0.5, and applying it to an image A as follows:
B = A > 0.5;
The matrix B will now be an M-by-N logical matrix with ones where A is greater than 0.5 and zeroes where A is less than or equal to 0.5.
If you have the Image Processing Toolbox, you could instead use the function GRAYTHRESH to pick a threshold and the function IM2BW to apply it:
B = im2bw(A,graythresh(A));
Once you do this, you can easily put the images into an M-by-N-by-100 logical matrix. Here's an example of how you could do this in a loop, assuming the variables M and N are defined:
allImages = false(M,N,100); %# Initialize the matrix to store all the images
for k = 1:100
%# Here, you would load your image into variable A
allImages(:,:,k) = im2bw(A,graythresh(A)); %# Threshold A and add it to
%# the matrix allImages
end