I'm trying to display live video from an external camera using the function "movie" after performing a 2x binning. My original video size is 768x576. However, when I bin my pixels, I get a 384x288 image that, when it's displayed, will look half the size of my original video. Is there any way I can increase the displayed size of the movie such that it looks the same size as the original? In other words, my pixel would look twice the size.
I have tried using set(gca,'Position'...) but it doesn't change the size of my movie.
Any suggestion?
I'll use the example movie as found on the documentation.
Suppose you have a bunch of frames:
figure('Renderer','zbuffer')
Z = peaks;
surf(Z);
axis tight
set(gca,'NextPlot','replaceChildren');
% Preallocate the struct array for the struct returned by getframe
F(20) = struct('cdata',[],'colormap',[]);
% Record the movie
for j = 1:20
surf(.01+sin(2*pi*j/20)*Z,Z)
F(j) = getframe;
end
At the end of help movie, it says:
MOVIE(H,M,N,FPS,LOC) specifies the location to play the movie
at, relative to the lower-left corner of object H and in
pixels, regardless of the value of the object's Units property.
LOC = [X Y unused unused]. LOC is a 4-element position
vector, of which only the X and Y coordinates are used (the
movie plays back using the width and height in which it was
recorded).
Thus, there is no way to display the movie at a bigger size than at which is was recorded. You'll have to blow up the pixels to make it display at larger size:
% blow up the pixels
newCdata = cellfun(#(x) x(...
repmat(1:size(x,1),N,1), ... % like kron, but then
repmat(1:size(x,2), N,1), :), ... % a bit faster, and suited
{F.cdata}, 'UniformOutput', false); % for 3D arrays
% assign all new data back to the movie
[F.cdata] = newCdata{:};
% and play the resized movie
movie(F,10)
Note that this won't win any prizes for readability, so if you're going to use this, please include a comment describing what it does.
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)
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.
So I have a quite big binary file that contains the information of about 70 video frames.
I read the binary file into MATLAB using the following
fid = fopen('data.binary');
B = fread(fid,'int64');
fclose(fid);
But then the variable B still contains a huge number of data. So I was wondering how can we split the variable B such that I can get data from one frame only one by one. Like let's say 30 FPS.
Is that even possible?
Thanks
PS: the pixel precision is uint8 and the Frame size 424X512. This is the code I am using:
fid = fopen('C:\KinectData\Depth\Depth_Raw_0.binary');
B = fread(fid,'uint8');
fclose(fid);
B = uint8(B);
Z = B(1:217088)
n = 424; % No. of columns of T
BB = reshape(Z, n,[]);
BB = uint8(BB);
imshow(BB)
But the picture isn't quite there yet.
OK, so we know a few things given your comments:
Each frame is 424 x 512
The precision of each element in your video is uint8
This is a grayscale video, so colour is not going to be considered
I'm going to assume your data is read in row major format. Bear in mind that MATLAB reads in data in column major format if you want to read in the data as a matrix, so you'll have to do a transpose operation, and ensure that you read the data into a transposed matrix first.
What I'm going to do is put each frame into a cell entry inside a cell array. The reason why I'm doing this is because we don't know how many frames are really in your sequence. You said "70 or so" frames, and since we don't know the exact number, we will dynamically populate the cell array as we go.
The code you have written will predominantly be the same, but we're going to run a while loop until what we read in from file is empty. In the while loop, we will read one frame at a time and store it into the cell array. I'll also make a counter that counts the number of frames we have to for later, and you'll see why. As such:
%// Open the file
fid = fopen('C:\KinectData\Depth\Depth_Raw_0.binary');
col = 424; %// Change if the dimensions are not proper
row = 512;
frames = {}; %// Empty cell array - Put frames in here
numFrames = 0; %// Let's record the number of frames too
while (true) %// Until we reach the end of the file:
B = fread(fin, [col row],'uint8=>uint8'); %// Read in one frame at a time
if (isempty(B)) %// If there are no more frames, get out
break;
end
frames{end+1} = B.'; %// Transpose to make row major and place in cell array
numFrames = numFrames + 1; %// Count frame
end
%// Close the file
fclose(fid);
As such, if you want to access the ith frame, you would simply do:
frm = frames{i};
As an additional bonus, you can play this as a movie in MATLAB. What we can do is preallocate a movie structure that is compatible to play the movie, then when you run the movie command, this will play the frames for you. Let's specify a frame rate of 10 fps, so that it will play slow enough to see the results. Therefore, when you're done do something like this:
%// Preallocate the movie structure array
movieFrames(numFrames) = struct('cdata',[],'colormap',[]);
for idx = 1 : numFrames
img = frames{idx};
movieFrames(idx) = im2frame(cat(3, img, img, img));
end
figure;
imshow(movieFrames(1).cdata); %// Show first frame to establish figure size
movie(movieFrames, 1, 10); %// Play the movie once at 10 FPS
Note that movies can only be played in colour, and so you would have to make your grayscale image artificially into colour. A colour frame is a 3D matrix, where each 2D slice tells you the amount of red, green or blue. For grayscale, each of these slices are the same, and so you would just replicate each grayscale frame for each slice. I used cat to make the grayscale frame into a 3D matrix. I also use im2frame to convert each image into a movie frame structure compatible to be played with movie.
Small caveat
I don't have access to your binary file, so this code is untested. Use at your own risk!
I have another problem today:
I have a binary matrix t, in which 1 represents a river channel, 0 represents flood plane and surrounding mountains:
t = Alog>10;
figure
imshow(t)
axis xy
For further calculations, I would like to expand the area of the riverchannel a few pixels in each direction. Generally speaking, I want to have a wider channel displayed in the image, to include a larger region in a later hydraulic model.
Here is my attempt, which does work in certain regions, but in areas where the river runs diagonal to the x-y axis, it does not widen the channel. There seems to be a flow in approaching this, which I cannot quite grasp.
[q,o] = find(t == 1);
qq = zeros(length(q),11);
oo = zeros(length(o),11);
% add +-5 pixel to result
for z=1:length(q)
qq(z,:) = q(z)-5:1:q(z)+5;
oo(z,:) = o(z)-5:1:o(z)+5;
end
% create column vectors
qq = qq(:);
oo = oo(:);
cords = [oo qq]; % [x y]
% remove duplicates
cords = unique(cords,'rows');
% get limits of image
[limy limx] = size(t);
% restrict to x-limits
cords = cords(cords(:,1)>=1,:);
cords = cords(cords(:,1)<=limx,:);
% restrict to y-limits
cords = cords(cords(:,2)>=1,:);
cords = cords(cords(:,2)<=limy,:);
% test image
l = zeros(size(img));
l(sub2ind(size(l), cords(:,2)',cords(:,1)')) = 1;
figure
imshow(l)
axis xy
This is the image I get:
It does widen the channel in some areas, but generally there seems to be a flaw with my approach. When I use the same approach on a diagonal line of pixels, it will not widen the line at all, because it will just create more pairs of [1 1; 2 2; 3 3; etc].
Is there a better approach to this or even something from the realm of image processing?
A blur filter with a set diameter should be working somewhat similar, but I could not find anything helpful...
PS: I wasn't allowed to add the images, although I already have 10 rep, so here are the direct links:
http://imageshack.us/a/img14/3122/channelthin.jpg
http://imageshack.us/a/img819/1787/channelthick.jpg
If you have the image processing toolbox, you should use the imdilate function. This performs the morphological dilation operation. Try the following code:
SE = strel('square',3);
channelThick = imdilate(channelThin,SE);
where SE is a 3x3 square structuring element used to dilate the image stored in channelThin. This will expand the regions in channelThin by one pixel in every direction. To expand more, use a larger structuring element, or multiple iterations.
You may apply morphological operations from image processing. Morphological dilation can be used in your example.
From the image processing toolbox, you can use bwmorth command BW2 = bwmorph(BW,'dilate') or imdilate command IM2 = imdilate(IM,SE).
Where IM is your image and SE is the structuring element. You can set SE = ones(3); to dilate the binary image by "one pixel" - but it can be changed depending on your application. Or you can dilate the image several times with the same structuring element if needed.
Let's say I have 9 MxN black and white images that are in some way related to one another (i.e. time lapse of some event). What is a way that I can display all of these images on one surface plot?
Assume the MxN matrices only contain 0's and 1's. Assume the images simply contain white lines on a black background (i.e. pixel value == 1 if that pixel is part of a line, 0 otherwise). Assume images are ordered in such a way as to suggest movement progression of line(s) in subsequent images. I want to be able to see a "side-view" (or volumetric representation) of these images which will show the surface that a particular line "carves out" in its movement across the images.
Coding is done in MATLAB. I have looked at plot (but it only does 2D plots) and surf, which does 3D plots but doesn't work for my MxNx9 matrix of images. I have also tried to experiment with contourslice, but not sure what parameters to pass it.
Thanks!
Mariya
Are these images black and white with simple features on a "blank" field, or greyscale, with more dense information?
I can see a couple of approaches.
You can use movie() to display a sequence of images as an animation.
For a static view of sparse, simple data, you could plot each image as a separate layer in a single figure, giving each layer a different color for the foreground, and using AlphaData to make the background transparent so all the steps in the sequenc show through. The gradient of colors corresponds to position in the image sequence. Here's an example.
function plotImageSequence
% Made-up test data
nLayers = 9;
x = zeros(100,100,nLayers);
for i = 1:nLayers
x(20+(3*i),:,i) = 1;
end
% Plot each image as a "layer", indicated by color
figure;
hold on;
for i = 1:nLayers
layerData = x(:,:,i);
alphaMask = layerData == 1;
layerData(logical(layerData)) = i; % So each layer gets its own color
image('CData',layerData,...
'AlphaData',alphaMask,...
'CDataMapping','scaled');
end
hold off
Directly showing the path of movement a "line" carves out is hard with raster data, because Matlab won't know which "moved" pixels in two subsequent images are associated with each other. Don't suppose you have underlying vector data for the geometric features in the images? Plot3() might allow you to show their movement, with time as the z axis. Or you could use the regular plot() and some manual fiddling to plot the paths of all the control points or vertexes in the geometric features.
EDIT: Here's a variation that uses patch() to draw each pixel as a little polygon floating in space at the Z level of its index in the image sequence. I think this will look more like the "surface" style plots you are asking for. You could fiddle with the FaceAlpha property to make dense plots more legible.
function plotImageSequencePatch
% Made-up test data
nLayers = 6;
sz = [50 50];
img = zeros(sz(1),sz(2),nLayers);
for i = 1:nLayers
img(20+(3*i),:,i) = 1;
end
% Plot each image as a "layer", indicated by color
% With each "pixel" as a separate patch
figure;
set(gca, 'XLim', [0 sz(1)]);
set(gca, 'YLim', [0 sz(2)]);
hold on;
for i = 1:nLayers
layerData = img(:,:,i);
[x,y] = find(layerData); % X,Y of all pixels
% Reshape in to patch outline
x = x';
y = y';
patch_x = [x; x+1; x+1; x];
patch_y = [y; y; y+1; y+1];
patch_z = repmat(i, size(patch_x));
patch(patch_x, patch_y, patch_z, i);
end
hold off