{"id":209,"date":"2008-05-07T08:49:55","date_gmt":"2008-05-07T12:49:55","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2008\/05\/07\/lookup-tables-for-binary-image-processing\/"},"modified":"2019-10-28T09:30:43","modified_gmt":"2019-10-28T13:30:43","slug":"lookup-tables-for-binary-image-processing","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2008\/05\/07\/lookup-tables-for-binary-image-processing\/","title":{"rendered":"Lookup tables for binary image processing"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>Today I'm introducing a short series about using <i>lookup tables<\/i> to implement neighborhood operations in binary images.  This is a fast implementation technique that works for small neighborhoods,\r\n      typically 2-by-2 or 3-by-3.\r\n   <\/p>\r\n   <p>My tentative plan is to do three posts on this algorithm topic:<\/p>\r\n   <p>1. Explain the basic idea (today)<\/p>\r\n   <p>2. Show some examples using Image Processing Toolbox functions<\/p>\r\n   <p>3. Explain an algorithm optimization we recently put in the toolbox.<\/p>\r\n   <p>Let's talk 3-by-3 binary neighborhoods.  Here's one:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = [0 0 1; 1 1 0; 1 0 0]<\/pre><pre style=\"font-style:oblique\">\r\nbw =\r\n\r\n     0     0     1\r\n     1     1     0\r\n     1     0     0\r\n\r\n<\/pre><p>Here's another:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = [1 0 0; 1 0 0; 0 1 0]<\/pre><pre style=\"font-style:oblique\">\r\nbw =\r\n\r\n     1     0     0\r\n     1     0     0\r\n     0     1     0\r\n\r\n<\/pre><p>OK, that might get old real fast.<\/p>\r\n   <p><b>QUESTION:<\/b> How many different 3-by-3 binary neighborhoods are there?\r\n   <\/p>\r\n   <p>Each pixel in the neighborhood can take on only two values, and there are nine pixels in the neighborhood, so the answer is:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">2^9<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n   512\r\n\r\n<\/pre><p>That's not so many different possibilities, although it would certainly be tedious to write them all out by hand!  Is there\r\n      an easy way to generate them?\r\n   <\/p>\r\n   <p>I'm sure there are lots of reasonable methods.  One way, used by the Image Processing Toolbox function <tt>makelut<\/tt>, is to use the 9-bit binary representation of the integers from 0 to 511.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">label = 5;\r\nbin = dec2bin(label, 9)<\/pre><pre style=\"font-style:oblique\">\r\nbin =\r\n\r\n000000101\r\n\r\n<\/pre><p><tt>bin<\/tt> is a 9-character string.  A logical comparison and a reshape turns it into a binary neighborhood:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = reshape(bin == <span style=\"color: #A020F0\">'1'<\/span>, 3, 3)<\/pre><pre style=\"font-style:oblique\">\r\nbw =\r\n\r\n     0     0     1\r\n     0     0     0\r\n     0     0     1\r\n\r\n<\/pre><p>Just repeat this for the other 511 integers in the range [0,511] and you'll have all possible 3-by-3 neighborhoods.  Compute\r\n      the output of your operation for each one and save the result in a table.\r\n   <\/p>\r\n   <p>Then use this procedure to implement your operation:<\/p><pre>For each input pixel:\r\n  Extract the 3-by-3 neighborhood\r\n  Compute the table index corresponding to the neighborhood\r\n  Insert the table value at that index into the output image<\/pre><p>Computing the table index corresponding to a given neighborhood can be done by using <tt>bin2dec<\/tt>.  Note that <tt>bin2dec<\/tt> takes a string, so we have to do a little work first to convert the binary neighborhood to a string of '0' and '1' characters.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">str = repmat(<span style=\"color: #A020F0\">'0'<\/span>, 1, 9);\r\nstr(bw(:)') = <span style=\"color: #A020F0\">'1'<\/span>;\r\nbin2dec(str)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n     5\r\n\r\n<\/pre><p>And that's the heart of the lookup table algorithm for binary image neighborhood processes.<\/p>\r\n   <p>In my next post on this topic, I'll introduce the Image Processing Toolbox functions <tt>makelut<\/tt> and <tt>applylut<\/tt> and show examples illustrating their use.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_7af4156ed28d4ecb80d16ddabbf1cc53() {\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='7af4156ed28d4ecb80d16ddabbf1cc53 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 7af4156ed28d4ecb80d16ddabbf1cc53';\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 2008 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_7af4156ed28d4ecb80d16ddabbf1cc53()\"><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.6<br><\/p>\r\n<\/div>\r\n<!--\r\n7af4156ed28d4ecb80d16ddabbf1cc53 ##### SOURCE BEGIN #####\r\n%%\r\n% Today I'm introducing a short series about using _lookup tables_\r\n% to implement neighborhood operations in binary images.  This is a\r\n% fast implementation technique that works for small neighborhoods,\r\n% typically 2-by-2 or 3-by-3.\r\n%\r\n% My tentative plan is to do three posts on this algorithm topic:\r\n%\r\n% 1. Explain the basic idea (today)\r\n%\r\n% 2. Show some examples using Image Processing Toolbox functions\r\n%\r\n% 3. Explain an algorithm optimization we recently put in the\r\n% toolbox.\r\n%\r\n% Let's talk 3-by-3 binary neighborhoods.  Here's one:\r\n\r\nbw = [0 0 1; 1 1 0; 1 0 0]\r\n\r\n%%\r\n% Here's another:\r\n\r\nbw = [1 0 0; 1 0 0; 0 1 0]\r\n\r\n%%\r\n% OK, that might get old real fast.\r\n%\r\n% *QUESTION:* How many different 3-by-3 binary neighborhoods are\r\n% there?\r\n%\r\n% Each pixel in the neighborhood can take on only two values, \r\n% and there are nine pixels in the neighborhood, so the answer is:\r\n\r\n2^9\r\n\r\n%%\r\n% That's not so many different possibilities, although it \r\n% would certainly be tedious to write them all out by hand!  Is\r\n% there an easy way to generate them?\r\n%\r\n% I'm sure there are lots of reasonable methods.  One way, used by\r\n% the Image Processing Toolbox function |makelut|, is to use the\r\n% 9-bit binary representation of the integers from 0 to 511.\r\n\r\nlabel = 5;\r\nbin = dec2bin(label, 9)\r\n\r\n%%\r\n% |bin| is a 9-character string.  A logical comparison and a reshape\r\n% turns it into a binary neighborhood:\r\n\r\nbw = reshape(bin == '1', 3, 3)\r\n\r\n%%\r\n% Just repeat this for the other 511 integers in the range [0,511]\r\n% and you'll have all possible 3-by-3 neighborhoods.  Compute the\r\n% output of your operation for each one and save the result in a\r\n% table.\r\n%\r\n% Then use this procedure to implement your operation:\r\n%\r\n%  For each input pixel:\r\n%    Extract the 3-by-3 neighborhood\r\n%    Compute the table index corresponding to the neighborhood\r\n%    Insert the table value at that index into the output image\r\n\r\n%%\r\n% Computing the table index corresponding to a given neighborhood\r\n% can be done by using |bin2dec|.  Note that |bin2dec| takes a\r\n% string, so we have to do a little work first to convert the binary\r\n% neighborhood to a string of '0' and '1' characters.\r\n\r\nstr = repmat('0', 1, 9);\r\nstr(bw(:)') = '1';\r\nbin2dec(str)\r\n\r\n%%\r\n% And that's the heart of the lookup table algorithm for binary\r\n% image neighborhood processes.\r\n%\r\n% In my next post on this topic, I'll introduce the Image\r\n% Processing Toolbox functions |makelut| and |applylut| and show\r\n% examples illustrating their use.\r\n\r\n##### SOURCE END ##### 7af4156ed28d4ecb80d16ddabbf1cc53\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   Today I'm introducing a short series about using lookup tables to implement neighborhood operations in binary images.  This is a fast implementation technique that works for small... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2008\/05\/07\/lookup-tables-for-binary-image-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":[490,262,116,170],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/209"}],"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=209"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/209\/revisions"}],"predecessor-version":[{"id":3600,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/209\/revisions\/3600"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=209"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=209"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=209"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}