{"id":385,"date":"2011-08-16T12:10:01","date_gmt":"2011-08-16T16:10:01","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2011\/08\/16\/dealing-with-really-big-images-block-processing\/"},"modified":"2019-10-29T16:52:01","modified_gmt":"2019-10-29T20:52:01","slug":"dealing-with-really-big-images-block-processing","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2011\/08\/16\/dealing-with-really-big-images-block-processing\/","title":{"rendered":"Dealing with &#8220;Really Big&#8221; Images: Block Processing"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p><i>I'd like to welcome back guest blogger <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/15472\">Brendan Hannigan<\/a>, for the second in a series of three posts on working with very large images in MATLAB.<\/i><\/p>\r\n      <p><hrule><\/p>\r\n   <\/introduction>\r\n   <h3>Contents<\/h3>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"#1\">Dealing with \"Really Big\" Images: Block Processing<\/a><\/li>\r\n         <li><a href=\"#2\">\"Sounds good.  let's do this!\"<\/a><\/li>\r\n         <li><a href=\"#3\">\"This seems familiar to me...\"<\/a><\/li>\r\n         <li><a href=\"#5\">\"Wait, didn't I read on CSSM that blockproc is way slower than blkproc ?\"<\/a><\/li>\r\n         <li><a href=\"#7\">\"What just happened?\"<\/a><\/li>\r\n         <li><a href=\"#9\">\"Uhm... 'block struct'?  That seems overly complicated\"<\/a><\/li>\r\n         <li><a href=\"#12\">\"What's with those lines all over your result?\"<\/a><\/li>\r\n         <li><a href=\"#13\">\"Ok, so how do I fix it?\"<\/a><\/li>\r\n         <li><a href=\"#14\">\"Ok great, you fixed it.  What does this have to do with large images?\"<\/a><\/li>\r\n         <li><a href=\"#16\">\"Hmm, ok yea that's cool.  What's the catch?\"<\/a><\/li>\r\n         <li><a href=\"#17\">\"You're killing me with these file format restrictions!  I don't use TIFF!\"<\/a><\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>Dealing with \"Really Big\" Images: Block Processing<a name=\"1\"><\/a><\/h3>\r\n   <p>Hi! This is Brendan Hannigan, back again to continue our discussion on working with very large images in MATLAB.  In the <a href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/08\/05\/dealing-with-really-big-images-viewing\/\">previous blog<\/a> I discussed a couple of different ways to view and explore large images using the Image Processing Toolbox.  Today I'll take\r\n      the next logical step down the \"large image workflow\" path and we'll explore how to process images that are too large to load\r\n      into memory.\r\n   <\/p>\r\n   <h3>\"Sounds good.  let's do this!\"<a name=\"2\"><\/a><\/h3>\r\n   <p>Since the entire image cannot be loaded into memory at one time, we opted for an incremental, file-to-file solution.  Basically\r\n      we want to read a part of your \"input\" image into memory, process it in some way, and then write the results back to a new\r\n      file, the \"output\" image.  We continue to do this until the entire image has been processed, avoiding Out of Memory errors.\r\n   <\/p>\r\n   <h3>\"This seems familiar to me...\"<a name=\"3\"><\/a><\/h3>\r\n   <p>The flow of data described here is very similar to an existing IPT function, <tt>blkproc<\/tt>, which allows for block processing of images, but like most other IPT functions, it only supports in-memory processing. Originally,\r\n      we considered expanding the scope of <tt>blkproc<\/tt> to support file-to-file workflows as well, but there were some syntactic and behavioral issues that I wasn't comfortable\r\n      with and we would've likely introduced some backwards incompatibilities.\r\n   <\/p>\r\n   <p>We instead opted for a completely new function in release R2009b.  The result? <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011a\/toolbox\/images\/ref\/blockproc.html\"><tt>blockproc<\/tt><\/a>! Very creative name right?  <tt>blockproc<\/tt> has all of the capabilities of <tt>blkproc<\/tt> and a LOT more!\r\n   <\/p>\r\n   <h3>\"Wait, didn't I read on CSSM that blockproc is way slower than blkproc ?\"<a name=\"5\"><\/a><\/h3>\r\n   <p>Ahem... well... Ok fine, yes, it <i>USED to be<\/i> slower.  The initial release of <tt>blockproc<\/tt> went out with what I will refer to simply as \"performance growth opportunities\" (sorry about that).\r\n   <\/p>\r\n   <p>However, with the release of R2010b, all that has changed!  <tt>blockproc<\/tt> performance was dramatically improved and is now comparable with <tt>blkproc<\/tt> for similar tasks.\r\n   <\/p>\r\n   <p>Let's have a quick look at how it works!<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #228B22\">% read input image<\/span>\r\nA = imread(<span style=\"color: #A020F0\">'peppers.png'<\/span>);\r\nimshow(A);\r\n<span style=\"color: #228B22\">% define block size and function to run on each block of data<\/span>\r\nblock_size = [64 64];\r\nmy_function = @(block_struct) block_struct.data(:,:,[3 2 1]);\r\n<span style=\"color: #228B22\">% call blockproc!<\/span>\r\nB = blockproc(A,block_size,my_function);\r\nfigure;\r\nimshow(B);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/blockproc_2_01.jpg\"> <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/blockproc_2_02.jpg\"> <h3>\"What just happened?\"<a name=\"7\"><\/a><\/h3>\r\n   <p>What we've done here is swapped the red and blue color channels of our RGB peppers image with some simple indexing.  <tt>blockproc<\/tt> did this one 64x64 block at a time and assembled the results into a single output image.  Things that were \"mostly red\" became\r\n      \"mostly blue\" and vice versa while the purple background remained mostly unchanged.\r\n   <\/p>\r\n   <p>Basically all <tt>blockproc<\/tt> needs is an input image, a block size, and a function handle to run (similar to <tt>blkproc<\/tt>);\r\n   <\/p>\r\n   <p>You may notice that I used an \"anonymous function\" to create the function handle <tt>my_function<\/tt>, but that's not necessary.  You can also provide a function handle to a function that's either defined on your path or sitting\r\n      in your current directory.  The only requirement is that the function must accept a \"block struct\" as it's sole input argument\r\n      (that we will pass to it, from inside of <tt>blockproc<\/tt>), and must return the processed data.\r\n   <\/p>\r\n   <h3>\"Uhm... 'block struct'?  That seems overly complicated\"<a name=\"9\"><\/a><\/h3>\r\n   <p>The block struct is a MATLAB struct that contains the block's image data (in the <tt>.data<\/tt> field) as well as several other pieces of useful information.  Most important among these is the <tt>.location<\/tt> field, which contains the location (in your input image) where the block came from. This <tt>.location<\/tt> information opens up a vast new world of potential uses for <tt>blockproc<\/tt> that we won't get into here.\r\n   <\/p>\r\n   <p>Most of the time you use <tt>blockproc<\/tt> you'll probably just use the <tt>.data<\/tt> field, but for any operation that changes depending on which block of the image you are processing, the <tt>.location<\/tt> field is key, and you'll be thanking me then!  You can check out the <tt>blockproc<\/tt> doc to learn more about what other information we package into the block struct.\r\n   <\/p>\r\n   <p>Now for a more \"real\" example, applying a low-pass filter to an image. First, the conventional way:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #228B22\">% read the original photo into memory<\/span>\r\norigp = imread(<span style=\"color: #A020F0\">'cameraman.tif'<\/span>);\r\nimshow(origp);\r\n<span style=\"color: #228B22\">% create a Gaussian low-pass filter<\/span>\r\nh = fspecial(<span style=\"color: #A020F0\">'gaussian'<\/span>,5,2);\r\n<span style=\"color: #228B22\">% compute the derived photo<\/span>\r\nderp1 = imfilter(origp,h);\r\nimshow(derp1);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/blockproc_2_03.jpg\"> <p>Now, with <tt>blockproc<\/tt>.  We will re-use the original photo, <tt>origp<\/tt>, as well as the Gaussian filter.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #228B22\">% create a function handle that we will apply to each block<\/span>\r\nmyFun = @(block_struct) imfilter(block_struct.data,h);\r\n<span style=\"color: #228B22\">% setup block size<\/span>\r\nblock_size = [64 64];\r\n<span style=\"color: #228B22\">% compute the new derived photo<\/span>\r\nderp2 = blockproc(origp,block_size,myFun);\r\nimshow(derp2);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/blockproc_2_04.jpg\"> <h3>\"What's with those lines all over your result?\"<a name=\"12\"><\/a><\/h3>\r\n   <p>What we see here are artifacts from block processing.  What happened? Well, as our function, <tt>imfilter<\/tt>, processes its input it will require some padding values near the edges of the image.  By default, <tt>imfilter<\/tt> will use \"zero padding\" to supply these \"pixels\" that lie beyond the boundary of the actual image data.\r\n   <\/p>\r\n   <p>But remember, <tt>blockproc<\/tt> processes each block totally independently from its neighbors, so as we processed each block, <tt>imfilter<\/tt> was diligently padding each one with zeros, causing these black lines to appear when the results were assembled into our\r\n      final output image.\r\n   <\/p>\r\n   <h3>\"Ok, so how do I fix it?\"<a name=\"13\"><\/a><\/h3>\r\n   <p>Luckily, we thought of that.  <tt>blockproc<\/tt> has several optional parameters that we can specify to control all aspects of padding and block borders. One in particular\r\n      is 'BorderSize', which lets us specify some \"overlap\" between blocks.  Since our filter is size 5x5, we need a 2 pixel overlap\r\n      between all of our blocks.  Here's how we do that:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">border_size = [2 2];\r\nderp3 = blockproc(origp,block_size,myFun,<span style=\"color: #A020F0\">'BorderSize'<\/span>,border_size);\r\nimshow(derp3);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/blockproc_2_05.jpg\"> <h3>\"Ok great, you fixed it.  What does this have to do with large images?\"<a name=\"14\"><\/a><\/h3>\r\n   <p>Right.  Here's the \"large data\" hook: <tt>blockproc<\/tt> can take string filenames as its \"input image\", and can subsequently write the \"output\" to a file by specifying a new <tt>'Destination'<\/tt> parameter.  When you specify a new output <tt>'Destination'<\/tt>, <tt>blockproc<\/tt> will not return the result image to the MATLAB workspace.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #228B22\">% specify a string filename as our input image<\/span>\r\norigp_filename = <span style=\"color: #A020F0\">'cameraman.tif'<\/span>;\r\n<span style=\"color: #228B22\">% specify a string filename as the 'Destination' of our output data<\/span>\r\nderp_filename = <span style=\"color: #A020F0\">'output.tif'<\/span>;\r\n<span style=\"color: #228B22\">% don't request an output argument this time!<\/span>\r\nblockproc(origp_filename,block_size,myFun,<span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'BorderSize'<\/span>,border_size,<span style=\"color: #A020F0\">'Destination'<\/span>,derp_filename);\r\nimshow(derp_filename);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/blockproc_2_06.jpg\"> <p>Now that the input and output are specified as files instead of workspace variables, you can run this command regardless of\r\n      image size.  Images are read, processed, and written incrementally, one block at a time.\r\n   <\/p>\r\n   <p>Need to apply a filter on a 3 gigabyte image?  No problem!  Trying to segment vegetation from a few terabytes of satellite\r\n      imagery?  No problem!\r\n   <\/p>\r\n   <h3>\"Hmm, ok yea that's cool.  What's the catch?\"<a name=\"16\"><\/a><\/h3>\r\n   <p>There's no catch!  Ok, there's a small catch.  <tt>blockproc<\/tt> only supports reading and writing to TIFF and JPEG2000 format files \"natively\".\r\n   <\/p>\r\n   <h3>\"You're killing me with these file format restrictions!  I don't use TIFF!\"<a name=\"17\"><\/a><\/h3>\r\n   <p>Hey don't worry!  We have you covered.  I said that <tt>blockproc<\/tt> only supports TIFF and JPEG2000 \"natively\".  What I meant by that is <tt>blockproc<\/tt> has \"built-in\" support for those file formats, but the function can \"adapt\" (hint,hint) to many other formats... which I\r\n      will talk about next time.\r\n   <\/p>\r\n   <p>Stay tuned!<\/p>\r\n   <p><hrule><\/p>\r\n   <p><i>Thanks, Brendan. -SE<\/i><\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_7ab6ee5bf98647319813ab29c65ddfd4() {\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='7ab6ee5bf98647319813ab29c65ddfd4 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 7ab6ee5bf98647319813ab29c65ddfd4';\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        author = 'Steve Eddins';\r\n        copyright = 'Copyright 2011 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 author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\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      \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_7ab6ee5bf98647319813ab29c65ddfd4()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.12<br><\/p>\r\n<\/div>\r\n<!--\r\n7ab6ee5bf98647319813ab29c65ddfd4 ##### SOURCE BEGIN #####\r\n%%\r\n% _I'd like to welcome back guest blogger\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/15472\r\n% Brendan Hannigan>, for the second in a series of three posts on working with \r\n% very large images in MATLAB._\r\n%\r\n% <html><hrule><\/html>\r\n\r\n%% Dealing with \"Really Big\" Images: Block Processing\r\n% Hi! This is Brendan Hannigan, back again to continue our discussion on\r\n% working with very large images in MATLAB.  In the\r\n% <https:\/\/blogs.mathworks.com\/steve\/2011\/08\/05\/dealing-with-really-big-images-viewing\/\r\n% previous blog> I discussed a couple of different ways to view and explore\r\n% large images using the Image Processing Toolbox.  Today I'll take the\r\n% next logical step down the \"large image workflow\" path and we'll explore\r\n% how to process images that are too large to load into memory.\r\n\r\n%% \"Sounds good.  let's do this!\"\r\n% Since the entire image cannot be loaded into memory at one time, we opted\r\n% for an incremental, file-to-file solution.  Basically we want to read a\r\n% part of your \"input\" image into memory, process it in some way, and then\r\n% write the results back to a new file, the \"output\" image.  We continue to\r\n% do this until the entire image has been processed, avoiding Out of Memory\r\n% errors.\r\n\r\n%% \"This seems familiar to me...\"\r\n% The flow of data described here is very similar to an existing IPT\r\n% function, |blkproc|, which allows for block processing of images, but\r\n% like most other IPT functions, it only supports in-memory processing.\r\n% Originally, we considered expanding the scope of |blkproc| to support\r\n% file-to-file workflows as well, but there were some syntactic and\r\n% behavioral issues that I wasn't comfortable with and we would've likely\r\n% introduced some backwards incompatibilities.\r\n\r\n%%\r\n% We instead opted for a completely new function in release R2009b.  The\r\n% result? <https:\/\/www.mathworks.com\/help\/releases\/R2011a\/toolbox\/images\/ref\/blockproc.html\r\n% |blockproc|>! Very creative name right?  |blockproc| has all of the\r\n% capabilities of |blkproc| and a LOT more!\r\n\r\n%% \"Wait, didn't I read on CSSM that |blockproc| is way slower than |blkproc| ?\"\r\n% Ahem... well... Ok fine, yes, it _USED to be_ slower.  The initial release\r\n% of |blockproc| went out with what I will refer to simply as \"performance\r\n% growth opportunities\" (sorry about that).\r\n%\r\n% However, with the release of R2010b, all that has changed!  |blockproc|\r\n% performance was dramatically improved and is now comparable with\r\n% |blkproc| for similar tasks.\r\n\r\n%%\r\n% Let's have a quick look at how it works!\r\n\r\n% read input image\r\nA = imread('peppers.png');\r\nimshow(A);\r\n% define block size and function to run on each block of data\r\nblock_size = [64 64];\r\nmy_function = @(block_struct) block_struct.data(:,:,[3 2 1]);\r\n% call blockproc!\r\nB = blockproc(A,block_size,my_function);\r\nfigure;\r\nimshow(B);\r\n\r\n%% \"What just happened?\"\r\n% What we've done here is swapped the red and blue color channels of our\r\n% RGB peppers image with some simple indexing.  |blockproc| did this one\r\n% 64x64 block at a time and assembled the results into a single output\r\n% image.  Things that were \"mostly red\" became \"mostly blue\" and vice versa\r\n% while the purple background remained mostly unchanged.\r\n\r\n%%\r\n% Basically all |blockproc| needs is an input image, a block size, and a\r\n% function handle to run (similar to |blkproc|);\r\n%\r\n% You may notice that I used an \"anonymous function\" to create the function\r\n% handle |my_function|, but that's not necessary.  You can also provide a\r\n% function handle to a function that's either defined on your path or\r\n% sitting in your current directory.  The only requirement is that the\r\n% function must accept a \"block struct\" as it's sole input argument (that\r\n% we will pass to it, from inside of |blockproc|), and must return the\r\n% processed data.\r\n\r\n%% \"Uhm... 'block struct'?  That seems overly complicated\"\r\n% The block struct is a MATLAB struct that contains the block's image data\r\n% (in the |.data| field) as well as several other pieces of useful\r\n% information.  Most important among these is the |.location| field, which\r\n% contains the location (in your input image) where the block came from.\r\n% This |.location| information opens up a vast new world of potential uses\r\n% for |blockproc| that we won't get into here.\r\n%\r\n% Most of the time you use |blockproc| you'll probably just use the |.data|\r\n% field, but for any operation that changes depending on which block of the\r\n% image you are processing, the |.location| field is key, and you'll be\r\n% thanking me then!  You can check out the |blockproc| doc to learn more\r\n% about what other information we package into the block struct.\r\n\r\n\r\n%%\r\n% Now for a more \"real\" example, applying a low-pass filter to an image.\r\n% First, the conventional way:\r\n\r\n% read the original photo into memory\r\norigp = imread('cameraman.tif');\r\nimshow(origp);\r\n% create a Gaussian low-pass filter\r\nh = fspecial('gaussian',5,2);\r\n% compute the derived photo\r\nderp1 = imfilter(origp,h);\r\nimshow(derp1);\r\n\r\n%%\r\n% Now, with |blockproc|.  We will re-use the original photo, |origp|, as\r\n% well as the Gaussian filter.\r\n\r\n% create a function handle that we will apply to each block\r\nmyFun = @(block_struct) imfilter(block_struct.data,h);\r\n% setup block size\r\nblock_size = [64 64];\r\n% compute the new derived photo\r\nderp2 = blockproc(origp,block_size,myFun);\r\nimshow(derp2);\r\n\r\n%% \"What's with those lines all over your result?\"\r\n% What we see here are artifacts from block processing.  What happened?\r\n% Well, as our function, |imfilter|, processes its input it will require\r\n% some padding values near the edges of the image.  By default, |imfilter|\r\n% will use \"zero padding\" to supply these \"pixels\" that lie beyond the\r\n% boundary of the actual image data.\r\n%\r\n% But remember, |blockproc| processes each block totally independently from\r\n% its neighbors, so as we processed each block, |imfilter| was diligently\r\n% padding each one with zeros, causing these black lines to appear when the\r\n% results were assembled into our final output image.\r\n\r\n%% \"Ok, so how do I fix it?\"\r\n% Luckily, we thought of that.  |blockproc| has several optional parameters\r\n% that we can specify to control all aspects of padding and block borders.\r\n% One in particular is 'BorderSize', which lets us specify some \"overlap\"\r\n% between blocks.  Since our filter is size 5x5, we need a 2 pixel overlap\r\n% between all of our blocks.  Here's how we do that:\r\n\r\nborder_size = [2 2];\r\nderp3 = blockproc(origp,block_size,myFun,'BorderSize',border_size);\r\nimshow(derp3);\r\n\r\n%% \"Ok great, you fixed it.  What does this have to do with large images?\"\r\n% Right.  Here's the \"large data\" hook: |blockproc| can take string\r\n% filenames as its \"input image\", and can subsequently write the \"output\"\r\n% to a file by specifying a new |'Destination'| parameter.  When you\r\n% specify a new output |'Destination'|, |blockproc| will not return the\r\n% result image to the MATLAB workspace.\r\n\r\n% specify a string filename as our input image\r\norigp_filename = 'cameraman.tif';\r\n% specify a string filename as the 'Destination' of our output data\r\nderp_filename = 'output.tif';\r\n% don't request an output argument this time!\r\nblockproc(origp_filename,block_size,myFun,...\r\n    'BorderSize',border_size,'Destination',derp_filename);\r\nimshow(derp_filename);\r\n\r\n%%\r\n% Now that the input and output are specified as files instead of workspace\r\n% variables, you can run this command regardless of image size.  Images are\r\n% read, processed, and written incrementally, one block at a time.\r\n%\r\n% Need to apply a filter on a 3 gigabyte image?  No problem!  Trying to\r\n% segment vegetation from a few terabytes of satellite imagery?  No\r\n% problem!\r\n\r\n%% \"Hmm, ok yea that's cool.  What's the catch?\"\r\n% There's no catch!  Ok, there's a small catch.  |blockproc| only supports\r\n% reading and writing to TIFF and JPEG2000 format files \"natively\".\r\n\r\n%% \"You're killing me with these file format restrictions!  I don't use TIFF!\"\r\n% Hey don't worry!  We have you covered.  I said that |blockproc| only\r\n% supports TIFF and JPEG2000 \"natively\".  What I meant by that is\r\n% |blockproc| has \"built-in\" support for those file formats, but the\r\n% function can \"adapt\" (hint,hint) to many other formats... which I will\r\n% talk about next time.\r\n\r\n%%\r\n% Stay tuned!\r\n\r\n%%\r\n% <html><hrule><\/html>\r\n%\r\n% _Thanks, Brendan. -SE_\r\n\r\n##### SOURCE END ##### 7ab6ee5bf98647319813ab29c65ddfd4\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      I'd like to welcome back guest blogger Brendan Hannigan, for the second in a series of three posts on working with very large images in MATLAB.\r\n      \r\n   \r\n   Contents\r\n  ... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/08\/16\/dealing-with-really-big-images-block-processing\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[823,711,725,292,370,76,36],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/385"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/comments?post=385"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/385\/revisions"}],"predecessor-version":[{"id":3751,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/385\/revisions\/3751"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}