Matlab vision.VideoFileWriter output is too big - matlab

I'm using Computer Vision System Toolbox in Matlab (R2015a, Windows7) to mask frames in the video file and write them into a new video file. By masking, I replace about 80% of the image with 0s and 1s:
videoFileReader = vision.VideoFileReader(fin);
videoFileWriter=vision.VideoFileWriter(fout, ...
'FileFormat', 'MPEG4', 'FrameRate', videoFileReader.info.VideoFrameRate);
frame = step(videoFileReader);
frame_new=mask(frame); %user function
step(videoFileWriter, frame_new);
The size (1080 x 1920 x 3) and the format (single) of the original and modified frames remain the same. Yet the masked videos are much bigger than the original ones, e.g. 1GB original video turns into nearly 4GB after masking. These large new files can not be opened (Windows 7, VLC media). Handbrake does not recognize them as a legit video file either.
When I mask only about 20% of the image, the masked video still come out large (up to 2.5Gb), but I have no problem opening these.
I tried adding 'VideoCompressor', 'MJPEG Compressor', but this gives a warning.
videoFileWriter=vision.VideoFileWriter(fin, 'FileFormat', 'MPEG4', ...
'FrameRate', videoFileReader.info.VideoFrameRate, 'VideoCompressor', 'MJPEG Compressor');
<...>
Warning: The VideoCompressor property is not relevant in this configuration of the System object.
We have TBs of video data to deidentify, so any suggestion would be much appreciated.
Thanks!

Larissa,
The size of the output MPEG-4 file can be controlled by adjusting the Quality parameter of the system object. This is a value from 0-100 which controls the output bitrate. So, higher the quality, larger the file. The default value is 75. The system object uses the Microsft API's to create MPEG-4 files.
Secondly, you need to call release(videoFileWriter) to complete writing the file. I just want to confirm that you are doing it and have just omitted it for the purposes of this code snippet.
The VideoCompressor property is not valid for MPEG-4 file format because the compressor to be used is fixed. You can choose that property only when you write out AVI files. However, you probably will not reach the same level of compression as MPEG-4.
Hope this helps.
Dinesh

Download ffmpeg here:https://git.ffmpeg.org/ffmpeg.git
For windows, open a bash terminal and run:
cat <path to folder with images>/*.png | <path to ffmpeg bin folder>/ffmpeg.exe -f image2pipe -i - output.mkv
For unix, do similar but download the appropriate build of ffmpeg.
I tried on a 7.90GB folder and got a 6.4MB .mkv-file. Works like a charm!

Related

Play an mp3 in Matlab

What I have
An mp3 file, 16kHz, 1 channel. Read like:
[data,Fs] = audioread('file.mp3');
This file is playable in Windows Media Player i.e., and works fine.
What I want
To play it inside matlab. After reading it, I've tried to play it, like:
soundsc(data);
However, it doesn't sound even near to how it should (neither using sound instead of soundsc).
The Problem then is..
How can I play this mp3 vector inside matlab? Is it even possible? Or do I need to convert it to other format so I can work with it? (wav I guess?)
You are missing the sample frequency. You need
soundsc(data, Fs)
If not present, the Fs argument defaults to 8192 Hz, which is not the correct one.
Also, note that if you don't need scaling you can use
sound(data, Fs)
which will run a little faster.

error using videoWriter in Matlab (asyncio)

I am trying to use videoWriter in Matlab 2013a on a Windows 7 64 bit machine. I also have Matlab 2009a installed (which could be the issue)
My code fails here:
vid = VideoWriter('TestVideo');
This gives me the following error:
Error using VideoWriter (line 240)
Undefined variable "asyncio" or class "asyncio.Channel".
Now if I do this:
vid = VideoWriter('TestVideo.mp4','MPEG-4');
I get this error:
Error using VideoWriter (line 168)
The specified profile is not valid.
I tried installing codecs, but that didn't help.
I read somewhere that someone had a similar problem, and it was due to a corrupt path and it could be caused by an older installation of Matlab (2007), but nothing about what was eventually done to fix it. I have tried to add the asyncio folder in the Matlab directory to the Matlab path, but again no luck.
I have further tried to find out what videoWriter does regarding asyncio, but cannot find any clues in the code, and I honestly don't really know what asyncio is.
Uninstalling Matlab 2009a is not an option.
So can anyone help me please?
BR Gorm
You need to use the second way of invoking VideoWriter.... so doing:
vid = VideoWriter('TestVideo.mp4','MPEG-4');
However, you are getting this error:
Error using VideoWriter (line 168) The specified profile is not valid.
This is due to the fact that you probably don't have the MPEG-4 codecs installed on your computer. You can verify this by doing this in MATLAB:
profiles = VideoWriter.getProfiles()
Run the above code in the Command Prompt. You get a list of all possible profiles that you can use for writing a video to file using VideoWriter. For example, I'm using MATLAB R2013a on Mac OS and this is what I get:
>> profiles = VideoWriter.getProfiles()
Summary of installed VideoWriter profiles:
Name Description
---------------- -----------------------------------------------------------------------
Archival Video file compression with JPEG 2000 codec with lossless mode enabled.
Grayscale AVI An AVI file with Grayscale Video Data
Indexed AVI An AVI file with Indexed Video Data
MPEG-4 A MPEG-4 file with H.264 Compression
Motion JPEG 2000 Video file compression with JPEG 2000 codec.
Motion JPEG AVI An AVI file with Motion JPEG compression
Uncompressed AVI An AVI file with uncompressed RGB24 video data
If you don't see MPEG-4 on your list of profiles, then you currently don't have the profile installed. As such, you will have to use one of the provided profiles that MATLAB has for you.
Since you're running Windows, one suggestion I have is to install the Windows 7 Codec Pack suite: http://www.windows7codecs.com/. I know you said that when you installed codecs, it didn't work but you can try the above link if you haven't done it already.
The above website contains all of the codecs you would need to play video files in Windows. This will hopefully allow you to use VideoWriter once you install the codecs.
So I found an answer to my own question. It was the path that was broken. Problem can be fixed easily by setting the Matlab search path to default.
This is an old question, but I also wanted to add my two cents. What solved the problem for me was looking at my Windows version. Many companies have a Windows N version installed on their computers. These versions don't have all of the codecs and software, needed for playing and creating media files. So if you are using Matlab at work this might be the problem.
The fix is downloading the Windows Media Feature Pack for N Versions and to make sure that no other codec packs, like K-Lite are installed.

save high resolution figures with parfor in matlab

I am using parfor loop to produce and save quite big number of figures. Due to the amount of data which will be presented in the figures, the resolution of the figures need to be high, something around 920 dpi. Using the normal for, the function works fine. But when we switch to parfor the resolution of the produced and saved pictures becomes totally low.
This is the figure handle creation part:
mainFig=figure('visible','off');
set(mainFig, 'Renderer', 'OpenGL');
and here is the saving part code:
print(mainFig,'-djpeg','-r920',strcat(MyDir,measure,sec_suffix,'.jpeg'))
any idea?
Thanks
This is a documented limitation of printing in headless mode:
Printing and Exporting without a Display
On a UNIX platform (including Macintosh), where you can start in
MATLAB nodisplay mode (matlabĀ -nodisplay), you can print using
most of the drivers you can use with a display and export to most of
the same file formats. The PostScript and Ghostscript devices all
function in nodisplay mode on UNIX platforms. The graphic devices
-djpeg, -dpng, -dtiff (compressed TIFF bitmaps), and -tiff
(EPS with TIFF preview) work as well, but under nodisplay they use
Ghostscript to generate output instead of using the drivers built into
MATLAB. However, Ghostscript ignores the -r option when generating
-djpeg, -dpng, -dtiff, and -tiff image files. This means that
you cannot vary the resolution of image files when running in
nodisplay mode.
The same is true for the -noFigureWindows startup option which
suppresses figures on all platforms. On Windows platforms the -dwin,
-dwinc, and -dsetup options operate as usual under
-noFigureWindows. However, the printpreview GUI does not function
in this mode. Naturally, the Windows only -dwin and -dwinc output
formats cannot be used on UNIX or Mac platforms with or without a
display.
Resolution Considerations
Use -rnumber to specify the resolution of the generated output. In
general, using a higher value will yield higher quality output but at
the cost of larger output files. It affects the resolution and output
size of all MATLAB built-in raster formats (which are identified in
column four of the table in Graphics Format Files).
Note: Built-in graphics formats are generated directly from MATLAB without conversion through the Ghostscript library. Also, in headless
(nodisplay) mode, writing to certain image formats is not done by
built-in drivers, as it is when a display is being used. These formats
are -djpeg, -dtiff, and -dpng. Furthermore, the -dhdf and
-dbmp formats cannot be generated in headless mode (but you can
substitute -dbmp16m for -dbmp). See "Printing and Exporting
without a Display" for details on printing when not using a display.
Unlike the built-in MATLAB formats, graphic output generated via
Ghostscript does not directly obey -r option settings. However, the
intermediate PostScript file generated by MATLAB as input for the
Ghostscript processor is affected by the -r setting and thus can
indirectly influence the quality of the final Ghostscript generated
output.
The effect of the -r option on output quality can be subtle at
ordinary magnification when using the OpenGL or ZBuffer renderers and
writing to one of the MATLAB built-in raster formats, or when
generating vector output that contains an embedded raster image (for
example, PostScript or PDF). The effect of specifying higher
resolution is more apparent when viewing the output at higher
magnification or when printed, since a larger -r setting provides
more data to use when scaling the image.
When generating fully vectorized output (as when using the Painters
renderer to output a vector format such as PostScript or PDF), the
resolution setting affects the degree of detail of the output; setting
resolution higher generates crisper output (but small changes in the
resolution may have no observable effect). For example, the gap widths
of lines that do not use a solid ('-') linestyle can be affected.
parfor spawns headless MATLAB instances (both Windows and Unix), so according to the above, the worker processes will fallback to Ghostscript printing driver which ignores the -r option.
When you export figures to raster graphics format (PNG, JPEG, TIFF, etc..) there are two cases:
if you printing in a normal session, MATLAB will use its built-in drivers to generate the graphics files directly, and should obey the resolution you specify
on the other hand, if you printing in headless mode, MATLAB will internally export the figure in Postscript vector format, and then use Ghostscript to convert it to the requested raster format using the following Ghostscript options:
-dNOPAUSE -q
-I"C:\Program Files\MATLAB\R2014a\sys\extern\win64\ghostscript\ps_files"
-I"C:\Program Files\MATLAB\R2014a\sys\extern\win64\ghostscript\fonts"
-sDEVICE=jpeg
-g576x432
-sOutputFile="file.jpeg"
as you can see, for some reason MATLAB uses a fixed target size 576x432 in headless mode when converting the PS file to other formats.
Here is some code for quick experimentation. I've tested it on a local parallel pool; All of the raster formats (PNG, JPEG, TIFF, PPM) had a fixed size of 576x432 (-r option ignored as previously explained). The PDF was also generated by converting the PS file to PDF (using -sDEVICE=pdfwrite Ghostscript output device).
fmt = {'ppm', 'tiff', 'png', 'jpeg', 'epsc2', 'pdf'};
outfolder = 'C:\Users\Amro\Desktop\print_test';
parpool(4)
parfor i=1:4
fig = figure(i);
% a random plot
ax = axes('Parent',fig);
plot(ax, cumsum(rand(1000,1)-0.5))
% save in each specified format (-r option is mostly ignored)
for f=1:numel(fmt)
print(fig, ['-d' fmt{f}], '-r920', ...
fullfile(outfolder,sprintf('plot%d.%s',i,fmt{f})));
drawnow
end
% also save FIG-file
hgsave(fig, sprintf('plot%d.fig',i))
close(fig);
end
delete(gcp)
The way I see it, you ought to export as an EPS file, and manually convert it to whatever format you need. That way you get to specify the target image size in the Ghostscript command invoked (I wouldn't bother with the print -r resolution option, because it has little effect on vector formats)
The alternative would be to export FIG-files inside parfor. You would then load them in a normal MATLAB session with a display, and serially print with the desired resolution and format:
for i=1:4
fig = hgload('plotXX.fig');
movegui(fig, 'center')
print(fig, '-djpeg', '-r920', 'outXX.jpeg')
close(fig)
end

Information about video.MultimediaFileWriter

I have used video.MultimediaFileWriter to write frames from input AVI video file to an output AVI video file. After the output file is created the size of the output file is very large. I have used VideoCompressor's provided in MATLAB options. For example: for an input video size of 3.42MB after using compression techniques provided by MATLAB the output video size is 98.5MB.
Can anyone tell me how to bring the output AVI file to size of the input file?
The creation of videos using H.264 was added in R2012a. Older versions support the less efficient codecs MJPEG and DV, which probably explain your large files. However, this is not a major problem because you can recompress your videos using free tools, such as VirtualDub and x264. Here is a tutorial.

ffmpeg vstats problems, Missing frames and misleading information!

The Problem I have is when using ffmpeg to encode a YUV using libx264 I don't get all the frame information in -vstats output. It raises the question of how reliable ffmpeg is, and therefore can any 'codec benchmark' review based on ffmpeg be trusted?
I am analysing codec's to determine how they perform. I am using ffmpeg and its -vstats option to look at an encoded movie frame by frame. the process I use:
RAW YUV -> bar-code each frame with frame number -> Bar-coded YUV
Bar-coded YUV -> encoded (e.g. with libx264) -> MKV -> Decoded to YUV
I can compare the two outputs ('Bar-coded YUV' & 'Decoded to YUV') using the bar-code in each frame. I can then compare, exactly, an original frame with an encoded frame using PSNR etc.
When encoding using libx264 and libdirac, there are some frame information which is missing. Other codecs, such as mpeg2video or even libvpx, don't have this problem.
I have found that libx264 vstats are missing for the first 40 to 50 frames. I have since proved that the missing information is actually the last 40 to 50 frames.
It also looks like ffmpeg calculates average bitrate based on the information in vstats. But as there is missing frames the average bitrate is less than what it should be.
Below are links to the average bitrate error example:
http://dl.dropbox.com/u/6743276/ffmpeg_probs/ffmpeg_av_bitrate_error.png
http://dl.dropbox.com/u/6743276/ffmpeg_probs/ffmpeg_av_bitrate_error.xlsx
Below is a link to the PSNR & f_size graph:
http://dl.dropbox.com/u/6743276/ffmpeg_probs/frame_mismatch.png
Below is a link to the output & command line options:
http://dl.dropbox.com/u/6743276/ffmpeg_probs/stderr.txt
I think this is also a bug, anyone clever enough to work it out might want to follow this tracker:
http://roundup.ffmpeg.org/issue2248
I have just discovered something which makes me very red in the face!! quite annoyed, but never mind :)
A fellow ffmpeg user pointed out that ffprobe should output more frame info, which it did. here is a link to his handy tip:
http://forums.creativecow.net/thread/291/71
Using this I found the following:
Actual average bitrate (ffprobe data): 8355.2776056338
Actual average bitrate (ffmpeg vstats data): 8406.23275471698
Ffmpeg -vstats avg_br: 7816.3
Reproduced above: 7816.32168421053
Ffmpeg standard error output 'bitrate=': 8365.8
Below is a link to my workings out:
http://dl.dropbox.com/u/6743276/ffmpeg_probs/ffprobe_vs_ffmpeg-vstats.xlsx
What I have discovered is I should have been using the average bitrate info from ffmpeg standard error output, it looks like the most reliable!