{"id":6291,"date":"2015-12-04T09:13:04","date_gmt":"2015-12-04T14:13:04","guid":{"rendered":"https:\/\/blogs.mathworks.com\/pick\/?p=6291"},"modified":"2015-12-04T09:32:34","modified_gmt":"2015-12-04T14:32:34","slug":"a-nice-easy-video-tutorial","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/pick\/2015\/12\/04\/a-nice-easy-video-tutorial\/","title":{"rendered":"A nice, easy video tutorial"},"content":{"rendered":"<div class=\"content\"><!--introduction--><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#9464153d-42ad-4c18-be51-103bec799ec3\">Time-Based Frame Reads<\/a><\/li><li><a href=\"#3b18cbd1-c121-4858-a1d8-9619e47ff312\"><tt>imshow<\/tt> and <tt>cdata<\/tt> instead of <tt>image<\/tt><\/a><\/li><li><a href=\"#ac20c5a0-ea24-43d6-b033-1fa3f0636eb2\">So...<\/a><\/li><li><a href=\"#fe93fd88-f2e6-4828-bec6-042e37fa08ab\">And finally:<\/a><\/li><li><a href=\"#4078c259-5586-4884-a123-d82dc33f6580\">Comments?<\/a><\/li><\/ul><\/div><p><a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/911\">Brett<\/a>'s Pick this week is <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/47726-video-processing-tutorial\">Video Processing Tutorial<\/a>, by prolific File Exchange author <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/1343420-image-analyst\">Image Analyst<\/a>.<\/p><p>For various reasons, I've been spending a lot of time working with videos in MATLAB lately--whether helping a customer work through some challenges, or developing new tools for detecting, tracking, and labeling regions of interest in individual frames. Getting started with video analysis can be a bit daunting--there are several options to confound the newer user, and it's easy to take mis-steps en route.<\/p><p>I particularly like Image Analyst's tutorial precisely because (as one recent commenter put it), it's: \"a nice starting place for video processing. Shows how easy it is for beginners to get into. Great job!\"<\/p><p>The tutorial is at just the right level to show video playback, and to demonstrate how to incorporate a simple frame-wise processing algorithm. Using a demo video ('rhinos.avi') that ships with the Image Processing Toolbox, Image Analyst shows how to:<\/p><div><ul><li>Extract the folder information for the target video:<\/li><\/ul><\/div><pre>folder = fileparts(which('rhinos.avi'));<\/pre><div><ul><li>Select a video from that directory:<\/li><\/ul><\/div><pre class=\"language-matlab\">movieFullFileName = fullfile(folder, <span class=\"string\">'rhinos.avi'<\/span>);\r\n<\/pre><div><ul><li>Create a video reader:<\/li><\/ul><\/div><pre class=\"language-matlab\">videoObject = VideoReader(movieFullFileName)\r\n<\/pre><div><ul><li>And use it to read and display frames. (I show the code with slight modifications here):<\/li><\/ul><\/div><pre class=\"language-matlab\">fontSize = 12;\r\nnumberOfFrames = videoObject.NumberOfFrames;\r\n<span class=\"keyword\">for<\/span> frame = 1 : numberOfFrames\r\nthisFrame = read(videoObject, frame);\r\n\timage(thisFrame);\r\n\tcaption = sprintf(<span class=\"string\">'Frame %4d of %d.'<\/span>, frame, numberOfFrames);\r\n\ttitle(caption, <span class=\"string\">'FontSize'<\/span>, fontSize);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p>There's much more.... Image Analyst shows the user the how to calculate and plot live statistics for the frame, and to perform some basic image analyses during the read\/display process, and to visualize the results while the video plays:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/VideoTutorialImage1.png\" alt=\"\"> <\/p><p>Optionally, you are prompted to write individual frames as images to a directory, and to recall them for subsequent playback. Very useful stuff!<\/p><p>I have a few suggestions for consideration:<\/p><h4>Time-Based Frame Reads<a name=\"9464153d-42ad-4c18-be51-103bec799ec3\"><\/a><\/h4><p>Image Analyst's video player uses \"frame-based\" reading. In R2014b, we introduced \"time-based\" frame reading that can be more efficient. To modify the code to use time-based reading, consider commenting out the call to <tt>videoObject.NumberOfFrames<\/tt>. (That triggers frame-based reading, and causes an error if you subsequently try to read using time-based modalities.) Instead, you can calculate the number of frames using <tt>numberOfFrames = round(videoObject.FrameRate * videoObject.Duration);<\/tt>, if you need to.<\/p><p>Then, instead of<\/p><pre class=\"language-matlab\"><span class=\"keyword\">for<\/span> frame = 1:numberOfFrames\r\n<\/pre><p>you can use a <tt>while<\/tt> loop:<\/p><pre class=\"language-matlab\"><span class=\"keyword\">while<\/span> hasFrame(videoObject)\r\n<\/pre><p>and a new <tt>readFrame<\/tt> command.<\/p><h4><tt>imshow<\/tt> and <tt>cdata<\/tt> instead of <tt>image<\/tt><a name=\"3b18cbd1-c121-4858-a1d8-9619e47ff312\"><\/a><\/h4><p>Also, I really like <tt>imshow<\/tt> for displaying images. It recognizes that the input matrix is an image, and maintains the aspect ratio. (<tt>image<\/tt>-displayed images can be stretched.) It also suppresses axes tick marks automatically, and has some other nice behaviors. Moreover, once you've created an \"image object,\" you can re-use it quite easily by modifying the \"CData\" of the object. There's no need to create a new image with each frame read:<\/p><h4>So...<a name=\"ac20c5a0-ea24-43d6-b033-1fa3f0636eb2\"><\/a><\/h4><pre class=\"language-matlab\">videoObject = VideoReader(movieFullFileName);\r\nframe = readFrame(videoObject);\r\nimg = imshow(frame);\r\n<span class=\"keyword\">while<\/span> hasFrame(videoObject)\r\n\tthisFrame = readFrame(videoObject);\r\n\timg.CData = thisFrame;\r\n\t  caption = sprintf(<span class=\"string\">'Frame %4d of %d.'<\/span>, <span class=\"keyword\">...<\/span>\r\n\t  \tround(videoObject.CurrentTime*videoObject.FrameRate), numberOfFrames);\r\n\ttitle(caption, <span class=\"string\">'FontSize'<\/span>, fontSize);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><h4>And finally:<a name=\"fe93fd88-f2e6-4828-bec6-042e37fa08ab\"><\/a><\/h4><p>Image Analyst uses a <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/struct.html\"><tt>struct<\/tt><\/a> to store the frame information. The new <a title=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/imagedatastore-object.html (link no longer works)\">\"image datastore\"<\/a> functionality (introduced in R2015b) facilitates easy reference to, and visualization of, individual images. (Image Analyst shows how to create a new video from the extracted frames, but you can alternatively just display them in a loop, using the <tt>readimage<\/tt> method of the datastore object. (I'll leave it to you to peruse the documentation for those new capabilities.)<\/p><h4>Comments?<a name=\"4078c259-5586-4884-a123-d82dc33f6580\"><\/a><\/h4><p><a href=\"https:\/\/blogs.mathworks.com\/pick\/?p=6291#respond\">Comments<\/a> and <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/47726-video-processing-tutorial#comments\">feedback<\/a> are always welcome! Let us know what you think.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_a427171a5230436b92df2e2122065391() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='a427171a5230436b92df2e2122065391 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' a427171a5230436b92df2e2122065391';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2015 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_a427171a5230436b92df2e2122065391()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2015b<br><\/p><\/div><!--\r\na427171a5230436b92df2e2122065391 ##### SOURCE BEGIN #####\r\n%% Video Processing Tutorial\r\n%% \r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/911 Brett>'s Pick this week\r\n% is\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/47726-video-processing-tutorial Video Processing Tutorial>, \r\n% by prolific File Exchange author <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/1343420-image-analyst Image Analyst>.\r\n%%\r\n% For various reasons, I've been spending a lot of time working with\r\n% videos in MATLAB latelyREPLACE_WITH_DASH_DASHwhether helping a customer work through\r\n% some challenges, or developing new tools for detecting, tracking,\r\n% and labeling regions of interest in individual frames. Getting\r\n% started with video analysis can be a bit dauntingREPLACE_WITH_DASH_DASHthere are several\r\n% options to confound the newer user, and it's easy to take mis-steps\r\n% en route.\r\n%% \r\n% I particularly like Image Analyst's tutorial precisely because (as\r\n% one recent commenter put it), it's: \"a nice starting place for video\r\n% processing. Shows how easy it is for beginners to get into. Great\r\n% job!\"\r\n%\r\n% The tutorial is at just the right level to show video playback, and\r\n% to demonstrate how to incorporate a simple frame-wise processing\r\n% algorithm. Using a demo video ('rhinos.avi') that ships with the\r\n% Image Processing Toolbox, Image Analyst shows how to:\r\n%%\r\n% * Extract the folder information for the target video:\r\n%%\r\n%  folder = fileparts(which('rhinos.avi'));\r\n%%\r\n% * Select a video from that directory:\r\n%%\r\n%   movieFullFileName = fullfile(folder, 'rhinos.avi');\r\n%%\r\n% * Create a video reader:\r\n%%\r\n%   videoObject = VideoReader(movieFullFileName)\r\n%%\r\n% * And use it to read and display frames. (I show the code\r\n% with slight modifications here):\r\n%%\r\n%   fontSize = 12;\r\n%   numberOfFrames = videoObject.NumberOfFrames;\r\n%   for frame = 1 : numberOfFrames\r\n%   thisFrame = read(videoObject, frame);\r\n% \timage(thisFrame);\r\n% \tcaption = sprintf('Frame %4d of %d.', frame, numberOfFrames);\r\n% \ttitle(caption, 'FontSize', fontSize);\r\n%   end\r\n%%\r\n% There's much more.... Image Analyst shows the user the how to\r\n% calculate and plot live statistics for the frame, and to perform\r\n% some basic image analyses during the read\/display process, and to\r\n% visualize the results while the video plays:\r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/VideoTutorialImage1.png>>\r\n% \r\n%%\r\n% Optionally, you are prompted to write individual frames as images to a\r\n% directory, and to recall them for subsequent playback. Very useful\r\n% stuff!\r\n%%\r\n% I have a few suggestions for consideration:\r\n%% Time-Based Frame Reads\r\n% \r\n% Image Analyst's video player uses \"frame-based\" reading. In R2014b,\r\n% we introduced \"time-based\" frame reading that can be more efficient.\r\n% To modify the code to use time-based reading, consider commenting\r\n% out the call to |videoObject.NumberOfFrames|. (That triggers\r\n% frame-based reading, and causes an error if you subsequently try to\r\n% read using time-based modalities.) Instead, you can calculate the\r\n% number of frames using |numberOfFrames = round(videoObject.FrameRate\r\n% * videoObject.Duration);|, if you need to.\r\n%\r\n% Then, instead of\r\n%%\r\n%   for frame = 1:numberOfFrames\r\n%% \r\n% you can use a |while| loop:\r\n%%\r\n%   while hasFrame(videoObject)\r\n%%\r\n% and a new |readFrame| command.\r\n%% |imshow| and |cdata| instead of |image|\r\n% Also, I really like |imshow| for displaying images. It recognizes\r\n% that the input matrix is an image, and maintains the aspect ratio.\r\n% (|image|-displayed images can be stretched.) It also suppresses axes\r\n% tick marks automatically, and has some other nice behaviors.\r\n% Moreover, once you've created an \"image object,\" you can re-use it\r\n% quite easily by modifying the \"CData\" of the object. There's no need\r\n% to create a new image with each frame read:\r\n%% So...\r\n%%\r\n%   videoObject = VideoReader(movieFullFileName);\r\n%   frame = readFrame(videoObject);\r\n%   img = imshow(frame);\r\n%   while hasFrame(videoObject)\r\n%   \tthisFrame = readFrame(videoObject);\r\n%   \timg.CData = thisFrame;\r\n% \t  caption = sprintf('Frame %4d of %d.', ...\r\n% \t  \tround(videoObject.CurrentTime*videoObject.FrameRate), numberOfFrames);\r\n%   \ttitle(caption, 'FontSize', fontSize);\r\n%   end\r\n\r\n%% And finally:\r\n% Image Analyst uses a\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/struct.html |struct|> to\r\n% store the frame information. The new\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/imagedatastore-object.html\r\n% \"image datastore\"> functionality (introduced in R2015b)\r\n% facilitates easy reference to, and visualization of, individual\r\n% images. (Image Analyst shows how to create a new video from the\r\n% extracted frames, but you can alternatively just display them in a\r\n% loop, using the |readimage| method of the datastore object. (I'll\r\n% leave it to you to peruse the documentation for those new\r\n% capabilities.)\r\n%% Comments?\r\n% <https:\/\/blogs.mathworks.com\/pick\/?p=6291#respond Comments> and\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/47726-video-processing-tutorial#comments feedback> are always welcome! Let us know what you think.\r\n##### SOURCE END ##### a427171a5230436b92df2e2122065391\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/VideoTutorialImage1.png\" onError=\"this.style.display ='none';\" \/><\/div><p>ContentsTime-Based Frame Readsimshow and cdata instead of imageSo...And finally:Comments?Brett's Pick this week is Video Processing Tutorial, by prolific File Exchange author Image Analyst.For... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/pick\/2015\/12\/04\/a-nice-easy-video-tutorial\/\">read more >><\/a><\/p>","protected":false},"author":34,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/6291"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/users\/34"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/comments?post=6291"}],"version-history":[{"count":5,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/6291\/revisions"}],"predecessor-version":[{"id":6298,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/6291\/revisions\/6298"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/media?parent=6291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/categories?post=6291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/tags?post=6291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}