this is my first question so I hope I am writing in the right place.
I am currently working with a Grasshopper3 camera, model: GS3-U3-50S5M-C from Point Grey Research connected to MATLAB.
I am recording a lot of frames at a time in grayscale and in order to avoid filling up my memory I would like to move some of the frames to my disk as stacked TIFFs during the recordings. The stacked TIFF format is needed for other programs used.
I am doing this by moving the recorded frames from the camera to the workspace using getdata. This creates a 4-D uint8 object containing height, width, color plane and frame number of the frames. In order to save the frames as a stacked TIFF I use a for loop with imwrite to save one frame at a time as shown below. However when I do this I most often get the error:
Error using imwrite (line 454) Unable to open file "C:\Users\My_User\Desktop\CraneStuff3\Name.tif" for writing. You might not have write permission.
When this happens MATLAB has typically saved some of the frames, e.g. if I have recorded 500 frames it might save 300 before giving me the error. Sometimes it manages to save every frame with no error, sometimes it only saves 30 frames before failing. I do not understand how it can save some frames and then claim that it cannot open the file for writing.
I have noticed, however, that if I instead save the file in "C:\Users\My_User\Documents\MATLAB" it seems to never give any error and save every frame as wanted.
Does anyone know why this is the case or how I can fix my problem?
I have included my code below here.
Note: I tried saving the frames as a .mat-file. To do this I had to use version '-v7.3' in save.
Thank you advance.
% Connect to camera:
vid = videoinput('pointgrey',1,'F7_Mono8_2448x2048_Mode0');
vid.TriggerRepeat = 100;
vid.FrameGrabInterval = 1;
% Make a recording:
start(vid)
pause(50)
stop(vid)
% Get data from camera to workspace:
data = getdata(vid,vid.FramesAvailable);
% Save data to disk one image at a time:
num = size(data);
output_name = fullfile('C:\Users\My_User\Desktop\CraneStuff3', ['Name' '.tif']);
for k = 1:num(4)
imwrite(data(:,:,:,k),output_name,'WriteMode','append');
end
One possible solution is to try saving each of the frames separately into a tiff file.
If you save a .mat file, better use savefast
Related
I am using a therm-app camera to take infra-red photos of bats. I would like to draw around parts of the bat and find the hottest, coldest and average temperature and do further analysis.
The software that comes with the camera doesn't let me draw polygons so I would like to load the image in another program such as MATLAB or maybe imageJ (also happy to use Python or other if that would work).
The camera creates 4 files total:
I have a .jpg file, however when I open this in MATLAB it just appears as an image and I think it is just opening as a normal image, not sure how to accurately get the temperatures from this. I used the following to open it:
im=imread('C:\18. Bats\20190321_064039.jpg');
imshow(im);
I also have three other files, two are metadata (e.g. show date-time emissivity settings etc.) and one is a text file.
The text file appears to show the temperature of every pixel in the image.
e.g. (for a photo that had a minimum temperature of 15deg and max of 20deg it would be a text file with a minimum value of 1500 and maximum value of 2000)
1516 1530 1530 1540 1600 1600 1600 1600 1536 1536 ........
This file looks very useful, just wondering if there is some way I can open this as an image, probably in a program like MATLAB, which I think has image analysis so that I could draw around certain parts of the image (e.g. the wing of the bat) and find the average, max, min etc.
Has anyone had experience with this type of thing, can I just assign colours to numbers somehow? Or maybe other people have done it already and there is a much easier way. I will keep searching on the internet also and try to find out.
Alternatively maybe I need to open the .jpg image, draw around different parts, write a program to find out which pixels I drew around, find these in the txt file and then do averaging etc? Or somehow link the values in the text file to the .jpg file.
Sorry if this is the wrong place to ask, I can't find an image processing site on stack exchange.
All help is really appreciated, I will continue searching on the internet in the meantime.
the following worked in the end, it was much much easier than I thought it would be. Now a big fan of MATLAB, I thought it could take days to do this.
Just pasting here in case it is useful to someone else. I'm sure there is a more elegant way to write the code, however this is the first time I've used MATLAB in 20 years :p Use at your own risk, I haven't double checked I'm getting the correct results yet (though will do before I use it for anything important).
edit, since writing this I've found that the output .txt file of temperatures is actually sensor temperatures which need to be corrected for emissivity and background temperature to obtain the target temperatures. (One way to do this is to use the software which comes free with the camera to create new output .csv files of temperatures and use those instead).
Thanks to bla who put me on the right track with dlmread.
M=dlmread('C:\18. Bats\20190321_064039\20190321_064039_temps.txt') % read in the text file as a matrix (call it M)
% note that file seems to be a list of temperature values for each pixel
% e.g. 1934 1935 1935 1960 2000 2199...
M = rot90( M , 1 ) % rotate M anti-clockwise by 1*90 (All the pictures were saved sideways for some reason so rotate for easier viewing)
a = min(M(:)); % find the minimum temperature in the image
b = max(M(:)); % find the maximum temperature in the image
imresize(M,1.64); % resize the image to fit the computer screen prior to showing it on the screen
imshow(M,[a b]); % show image on the screen and fit the colours so that white is the value with the highest temperature in the image (b) and black is the lowest (a).
h = drawpolygon('FaceAlpha',0); % Let the user draw a polygon around the region of interest (ROI)
%(this stops code until polygon is drawn)
maskOfROI = h.createMask(); % For each pixel in the image assign a binary number, pixels inside the polygon (ROI) area are given 1 outside are 0
selectedValues = M(maskOfROI); % Now get the image values for all pixels where the mask value is '1' (i.e. all pixels within the polygon) and call this selectedValues.
averageTemperature = mean(selectedValues); % Get the mean of selectedValues (i.e. mean of the temperatures inside the polygon area)
maxTemperature = max(selectedValues); % Get the max of selectedValues
minTemperature = min(selectedValues); % Get the min of selectedValues
I presently have a gui that captures avi file. It works as follows:
controller
The image in the controller is the preview from the camera. When I push the Start Record button, the program will catch the image with getsnapshot() function and writeVideo() function to write the image to a video file.
And I get time information with clock function after the getsnapshot() function. (I find when use [frame, metadata] = getsnapshot(obj), metadata is empty. I do not know why).
I want to ask if I can save the time information to the video file, (e.g., avi file) in real time. I do not know how to do it. Anyone has ideas?
I don't know of any way to add custom header fields to an AVI file to store your additional time information. However, you could add an extra row to the bottom of your image frame that contains the encoded time stamp information for that frame. This will depend on the format of your frame data, but here's an example to illustrate:
Let's say frame is your typical RGB (Truecolor) image, with three color planes and uint8 data values, like the built-in sample image 'peppers.png':
img = imread('peppers.png');
The clock function returns the current data and time as a date vector, which is a six-element double-precision vector. This requires 48 bytes of storage. We can cast the 1-by-6 double vector to a 1-by-48 uint8 vector using the typecast function, then add it to the beginning of an additional row of the red image plane (padding the rest of the row and other planes with zeroes automatically):
img(end+1, 1:48, 1) = typecast(clock, 'uint8');
The extra row at the bottom is fairly inconspicuous:
And we can reconstitute the time stamp and original image like so:
t = typecast(img(end, 1:48, 1), 'double');
img = img(1:(end-1), :, :);
I need to crop a specific area of a video in MATLAB to be replayed and saved as that specific area. Currently I only know of a way to separate all the frames, crop them, and then put them back together as a video - is there an easier way or tool to crop a video in MATLAB or am I just going to have to rely on frame-by-frame cropping?
Matlab is generally horrible for video processing. I would recommend using a generic video editor. If you have to use matlab, there are a couple of toolboxes on fileexchange which will serve your purpose (for short videos in the most generic formats and also require image toolbox).
Description
With Movie Editor you can:
- Load movies (avi's only)
- Cut movies
- Crop movies
- Split movies into separate color layers
- Rotate movies
- Save movies as avi or mpg (thanks to David Foti)
- Save independent frames as bmp, jpg, png, and tif
- You can always stroll through the movie using the slider and edittext underneath the image (maybe somebody can combine it with the 'Interactive MATLAB Movie Player' of Don Orofino.
Maybe you can add a function? The user interface is pretty self-explanatory. But questions are welcome. An example of a before- and after-movie are added to the zip-file.
Following is the code that I wrote a while ago to process video files. Before executing this file save the ROI1.m file in the path.
%frame by frame processing of video files
clear all;
close all;
clc;
mov=VideoReader('C:\Users\Syd_R\OneDrive\Desktop\entrap\holo_bright_10_MMStack_Pos0.ome.avi');
vidFrames=read(mov);
nFrames=mov.NumberOfFrames;
A=vidFrames(:,:,1);
for fr=1:nFrames
set(0,'DefaultFigureVisible','off')
elseX=vidFrames(:,:,fr);
if exist('position')==0
ROI1
else
imshow(elseX)
I2 = imcrop(elseX,[position(:,1) position(:,2) position(:,3) position(:,4)]);
end
mycell_h(fr)={I2};
end
close all;
set(0,'DefaultFigureVisible','on')
% This file should be saved (as ROI1.m) in the same path as this file will be called while executing the main file
% ROI
if exist('A')==1;
figure, imshow(A);
h = imrect(gca,[10 10 512 512]);
position = wait(h); % returns coordinates in "position" when user doubleclicks on rectangle
figure, imshow(A)
I2=imcrop(A,position);
phROI2=I2;
figure(11);
imshow(phROI2);
imwrite(phROI2, 'roi', 'tiff')
end;
The cropped frames will be saved in the cell [mycell_h]. To view the cropped frames, for example:
imshow(mycell_h{1,1})
I'm using matlab to interface with a scientific camera using mex, and my matlab program uses VideoWriter() to write the file to disc. The camera is RGB-capable, and if I write the file as such, the video is fine. However, for the current application, I need grayscale images, and so I'm using rgb2gray() to convert it. Unfortunately, when the analysis code tried to read the video file again, I get the error:
Error using VideoReader/init (line 450)
Unable to read the file. The file appears to be corrupt.
and attempting to read the video with VLC confirms it to be corrupt. The only difference in my code between they grayscale and colour versions is the line:
frame = rgb2gray(frame);
My whole writing section of code is:
vid = VideoWriter('testVid.avi');
vid.FrameRate = framerate;
vid.Quality = 100;
open(vid);
for i = 1 : frames;
%read frame data into variable 'frame'
frame = rgb2gray(frame);
writeVideo(vid,frame);
end
I've spent far too long fighting with this, any ideas?
You need to close the video object, using close(vid) after writing the last frame.
The function getframe captures whatever is visible on the screen. However in my application I want the figure to be invisible when storing its content in a matrix. So what the getframe does is that, for a short period, it makes the figure visible and captures its contents and then sets the 'visibile' property back to what it was before screen capture.
I do not want that flash happening on the screen. As well, saving in file and reading it back reduces speed. There has got to be a way to get around this.
hFig=figure('Visible','off'')
text ('String','ABC','fontsize',300)
imageData = getframe(hFig);
img = imageData.cdata; % img is what I am interested in
The only way I know to do this is to print the figure to a temporary file. For example:
%Create a figure
hFig=figure('Visible','off')
text ('String','ABC','fontsize',300)
%Save the figure to a tiff file using a salted name
tmpName = sprintf('Temp_Figure_%04d.tiff', floor(rand*1000));
print(['-f' num2str(hFig)], '-dtiff', tmpName)
%Read the data
img = imread(tmpName);
%Delete the temporary figure
delete(tmpName);
Not the prettiest thing, but it seems to work.