I have an avi-video-file. I would like to represent a frame from this video as 3 matrices (because colors are parameterized by 3 number ([red,green,blue] or [hue,saturation,value] or something else).
At the moment I have this code:
videoObject = mmreader(fname);
imageData = read(videoObject, [1 5])
So, as far as I understand I extract the first 5 frames from the video. But I do not understand in what format the imageData is given. For example, how can I get the green component of the color of the pixel from the third frame located at the row number 17 and column number 32?
Can anybody, please, help me with that?
As far as I understand it can be done in the following way. A particular frame can be reached in this way:
% Take frame number 7:
imageData = read(videoObject, 7);
Now if we want to know the read, green, blue component of the pixel in the column 1 and row 2 we need to do that:
impixel(imageData,1,2)
It will return 3 numbers (RGB component of the color of the pixel).
The format for imageData returned from the function read is a 4-D array where your dimensions are (in order) frame height, frame width, image depth (3 for RGB images), and number of frames. So, to get the green component of the pixel in row 17 and column 32 of the third frame, you would simply do this:
greenValue = imageData(17,32,2,3);
One side note: mmreader will be removed in a future MATLAB release in favor of VideoReader.
vidObj1 = mmreader('testballroom_0.avi'); %# Create a video file object
nFrames = vidObj1.NumberOfFrames; %# Get the number of frames
vidHeight1 = vidObj1.Height; %# Get the image height
vidWidth1 = vidObj1.Width; %# Get the image width
%# Preallocate the structure array of movie frames:
mov1(1:nFrames) = struct('cdata',zeros(vidHeight1,vidWidth1,3,'uint8'),...
'colormap',[]); %# Note that colormap is empty!
You can access the frames from mov1 :)
Related
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>
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 am writing a Matlab program to segment an image and then put a bounding box around the segmented image. My code was previously working, however I am now getting the error:
Error using rectangle
Value must be a 4 element vector
The array in question is BoundingBox created by regionprops, which should contain only four elements, however is for some reason containing more. Here is my code (the defaultSegment function returns a binary image):
function [ boundImage ] = boundSegment( input_image )
image = defaultSegment(input_image);
clear s;
s = regionprops(image, 'Area', 'BoundingBox');
numObj = numel(s);
index = 1;
for k = 1: numObj-1
if s(k+1).Area > s(index).Area
index = k+1;
else
index = index;
end
end
figure, imshow(input_image);
rectangle('Position',s(index).BoundingBox);
boundImage = null;
(I would actually prefer if my code could could directly put the bounding box on the image instead of subplotting it, but I haven't found a way to do that without the vision toolbox)
Thanks!
I suspect that image has more than two dimensions. Check that using size(image). BoundingBox will have four elements only if image has two dimensions. From Matlab's regionprops help:
'BoundingBox' — The smallest rectangle containing the region, a 1-by-Q *2 vector, where Q is the number of image dimensions: ndims(L), ndims(BW), or numel(CC.ImageSize).
The reason an image would have a third dimension is for multiple color channels. If you want to convert to grayscale for processing, use rgb2gray.
Continuing #shoelzer's answer regarding image with three channels,
I suspect you get color image because of your segmentation algorithm (defaultSegment) that paints each segment in a different color. try rgb2ind to convert image to a segmentation label 2D matrix
This is what i am trying to do in MATLAB but can't seem to get around achieving it
For each row in the filtered image, assign a value
of one to the pixels that have the minimum value
in that row and the other pixels to zero
Here's a solution:
img = imread('http://i.stack.imgur.com/tY3YE.jpg');
img = rgb2gray(img); %# transform jpeg color image to grayscale
minValue = min(img,[],2);
%# set the pixels equal to the minimum value to 1
bw = bsxfun(#eq,img,minValue);
When I run this on the image you linked, I get
Which shows that there are plenty of border effects from median filtering. Removing the border 10 pixels, i.e. with
img = img(10:end-9,10:end-9);
and running the code again, I find
Which makes quite a bit more sense.
I think you can achieve what you need through:
% Obtain the minimum in each row
mn = min(I,[],2);
% Set the pixels that are minimum to one, others to zero
eq = I == repmat(mn,1,size(I,2));
This code assumes that you have your image in I.
i have an image I of size 512x256.
i want to get some portion like a slice from this image I.
like i want I1 of size 512x50 .
To take a slice that includes the first 50 columns, and all rows, do the following
sliceOfImage = originalImage(:,1:50)
To take a slice that includes columns 100 to 149, call
sliceOfImage = originalImage(:,100:149)
etc.
x = [1:50]; % define the scope of x-axis (the "columns") for the portion of the image
y = [1:512]; %define the scope of y-axis (the "rows") for the portion of the image
I1 = I(x,y,:); % Create I1, the desired portion of the image. Assuming the original image is of RGB and you need to access all 3 colors.