{"id":128,"date":"2007-03-28T09:56:36","date_gmt":"2007-03-28T13:56:36","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/28\/neighbor-indexing\/"},"modified":"2019-10-23T08:48:31","modified_gmt":"2019-10-23T12:48:31","slug":"neighbor-indexing","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/28\/neighbor-indexing\/","title":{"rendered":"Neighbor indexing"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>In response to <a href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/20\/connected-component-labeling-part-3\/\">my last post about connected component labeling algorithms<\/a>, blog reader JanKees <a href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/20\/connected-component-labeling-part-3\/#comment-6597\">wanted to know<\/a> how to find neighboring pixel pairs programmatically.  Prompted by this question, I thought I would describe a MATLAB indexing\r\n      technique that is useful for various kinds of neighbor searching applications.\r\n   <\/p>\r\n   <p>To get started, let's first review linear indexing.  If you use a single subscript to index into a matrix, you access elements\r\n      in the matrix based on the way they are stored in memory, which is by columns.  For example:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">a = magic(3)<\/pre><pre style=\"font-style:oblique\">\r\na =\r\n\r\n     8     1     6\r\n     3     5     7\r\n     4     9     2\r\n\r\n<\/pre><p><tt>a(3,1)<\/tt> is the third element in the columnwise ordering of the elements of <tt>a<\/tt>, so <tt>a(3)<\/tt> gives you that element:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">a(3)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n     4\r\n\r\n<\/pre><p><tt>a(2,3)<\/tt> is the eighth columnwise element, so <tt>a(8)<\/tt> gives you that element:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">a(8)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n     7\r\n\r\n<\/pre><p>We call this single subscript a ''linear index''. You can use signed offsets to linear indices to get from a particular matrix\r\n      element to any of its neighbors.  For example, if you subtract 1 from an element's linear index, you get the location of the\r\n      element just above.  For a matrix with <tt>M<\/tt> rows, adding <tt>M<\/tt> to an element's linear index gives you the element just to the right.  (<b>Caveat:<\/b> This technique only works for elements that aren't on the outermost rows or columns of the matrix.)\r\n   <\/p>\r\n   <p>Let's apply this technique to finding the 4-connected neighborhood pairs for a simple binary image matrix.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = logical([ <span style=\"color: #0000FF\">...<\/span>\r\n    0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0\r\n    0 1 1 0 0 0 0\r\n    0 0 0 1 1 1 0\r\n    0 0 0 1 1 1 0\r\n    0 0 0 0 0 0 0 ])<\/pre><pre style=\"font-style:oblique\">\r\nbw =\r\n\r\n     0     0     0     0     0     0     0\r\n     0     1     1     0     0     0     0\r\n     0     1     1     0     0     0     0\r\n     0     0     0     1     1     1     0\r\n     0     0     0     1     1     1     0\r\n     0     0     0     0     0     0     0\r\n\r\n<\/pre><p>Step 1: Given the size of the matrix, compute neighborhood index offsets.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[M,N] = size(bw);\r\nnorth_offset = -1;\r\neast_offset = M;\r\nsouth_offset = 1;\r\nwest_offset = -M;<\/pre><p>Step 2: Find the linear indices for all the nonzero matrix elements.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">idx = find(bw)<\/pre><pre style=\"font-style:oblique\">\r\nidx =\r\n\r\n     8\r\n     9\r\n    14\r\n    15\r\n    22\r\n    23\r\n    28\r\n    29\r\n    34\r\n    35\r\n\r\n<\/pre><p>Step 3: Compute the values of all the north neighbors.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">north_idx = idx + north_offset;\r\nnorth_neighbors = bw(north_idx)<\/pre><pre style=\"font-style:oblique\">\r\nnorth_neighbors =\r\n\r\n     0\r\n     1\r\n     0\r\n     1\r\n     0\r\n     1\r\n     0\r\n     1\r\n     0\r\n     1\r\n\r\n<\/pre><p>Step 4: Construct the matrix of northern neighbor pairs. Here I'll use <tt>north_neighbors<\/tt> as a logical index to pick out elements where <tt>north_neighbors<\/tt> is nonzero.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">north_pairs = [idx(north_neighbors), north_idx(north_neighbors)]<\/pre><pre style=\"font-style:oblique\">\r\nnorth_pairs =\r\n\r\n     9     8\r\n    15    14\r\n    23    22\r\n    29    28\r\n    35    34\r\n\r\n<\/pre><p>Step 5: Repeat steps 3 and 4 for the other directions.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">east_idx = idx + east_offset;\r\neast_neighbors = bw(east_idx);\r\neast_pairs = [idx(east_neighbors), east_idx(east_neighbors)];\r\n\r\nsouth_idx = idx + south_offset;\r\nsouth_neighbors = bw(south_idx);\r\nsouth_pairs = [idx(south_neighbors), south_idx(south_neighbors)];\r\n\r\nwest_idx = idx + west_offset;\r\nwest_neighbors = bw(west_idx);\r\nwest_pairs = [idx(west_neighbors), west_idx(west_neighbors)];\r\n\r\nall_pairs = [north_pairs; east_pairs; south_pairs; west_pairs]<\/pre><pre style=\"font-style:oblique\">\r\nall_pairs =\r\n\r\n     9     8\r\n    15    14\r\n    23    22\r\n    29    28\r\n    35    34\r\n     8    14\r\n     9    15\r\n    22    28\r\n    23    29\r\n    28    34\r\n    29    35\r\n     8     9\r\n    14    15\r\n    22    23\r\n    28    29\r\n    34    35\r\n    14     8\r\n    15     9\r\n    28    22\r\n    29    23\r\n    34    28\r\n    35    29\r\n\r\n<\/pre><p><b>Note:<\/b> Generally, you need to prepad the matrix to make sure that no nonzero elements are on the boundaries. I didn't do that here\r\n      because my sample matrix didn't need it.  Just remember that prepadding changes the element locations and the neighbor offset\r\n      values, so you'll need to compensate for that in your own code. The details will vary depending on exactly what you are doing\r\n      with the neighbor values and locations.\r\n   <\/p>\r\n   <p>For more information about MATLAB indexing, including linear and logical indexing, here's a <a href=\"https:\/\/www.mathworks.com\/company\/newsletters\/articles\/matrix-indexing-in-matlab.html\">MATLAB Digest article<\/a> that <a href=\"https:\/\/blogs.mathworks.com\/loren\/\">Loren<\/a> and I wrote a few years ago.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_a8bfe116643b4cbca4a0f1829a3d7d74() {\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='a8bfe116643b4cbca4a0f1829a3d7d74 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' a8bfe116643b4cbca4a0f1829a3d7d74';\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 2007 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_a8bfe116643b4cbca4a0f1829a3d7d74()\"><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.4<br><\/p>\r\n<\/div>\r\n<!--\r\na8bfe116643b4cbca4a0f1829a3d7d74 ##### SOURCE BEGIN #####\r\n%% Neighbor indexing\r\n% In response to <https:\/\/blogs.mathworks.com\/steve\/2007\/03\/20\/connected-component-labeling-part-3\/\r\n% my last post about connected component labeling algorithms>, blog reader\r\n% JanKees <https:\/\/blogs.mathworks.com\/steve\/2007\/03\/20\/connected-component-labeling-part-3\/#comment-6597 \r\n% wanted to know> how to find neighboring pixel pairs\r\n% programmatically.  Prompted by this question, I thought I would describe\r\n% a MATLAB indexing technique that is useful for various kinds of neighbor\r\n% searching applications.\r\n%\r\n% To get started, let's first review linear indexing.  If you use a single\r\n% subscript to index into a matrix, you access elements in the matrix based\r\n% on the way they are stored in memory, which is by columns.  For example:\r\n\r\na = magic(3)\r\n\r\n%%\r\n% |a(3,1)| is the third element in the columnwise ordering of the elements\r\n% of |a|, so |a(3)| gives you that element:\r\n\r\na(3)\r\n\r\n%%\r\n% |a(2,3)| is the eighth columnwise element, so |a(8)| gives you that\r\n% element:\r\n\r\na(8)\r\n\r\n%%\r\n% We call this single subscript a ''linear index''. You can use signed offsets \r\n% to linear indices to get from a particular matrix element to any of its\r\n% neighbors.  For example, if you subtract 1 from an element's linear\r\n% index, you get the location of the element just above.  For a matrix with\r\n% |M| rows, adding |M| to an element's linear index gives you the element\r\n% just to the right.  (*Caveat:* This technique only works for elements that\r\n% aren't on the outermost rows or columns of the matrix.)\r\n%\r\n% Let's apply this technique to finding the 4-connected neighborhood pairs \r\n% for a simple binary image matrix.\r\n\r\nbw = logical([ ...\r\n    0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0\r\n    0 1 1 0 0 0 0\r\n    0 0 0 1 1 1 0\r\n    0 0 0 1 1 1 0\r\n    0 0 0 0 0 0 0 ])\r\n\r\n%%\r\n% Step 1: Given the size of the matrix, compute neighborhood index offsets.\r\n\r\n[M,N] = size(bw);\r\nnorth_offset = -1;\r\neast_offset = M;\r\nsouth_offset = 1;\r\nwest_offset = -M;\r\n\r\n%%\r\n% Step 2: Find the linear indices for all the nonzero matrix elements.\r\n\r\nidx = find(bw)\r\n\r\n%%\r\n% Step 3: Compute the values of all the north neighbors.\r\n\r\nnorth_idx = idx + north_offset;\r\nnorth_neighbors = bw(north_idx)\r\n\r\n%%\r\n% Step 4: Construct the matrix of northern neighbor pairs. Here I'll use\r\n% |north_neighbors| as a logical index to pick out elements where\r\n% |north_neighbors| is nonzero.\r\n\r\nnorth_pairs = [idx(north_neighbors), north_idx(north_neighbors)]\r\n\r\n%%\r\n% Step 5: Repeat steps 3 and 4 for the other directions.\r\n\r\neast_idx = idx + east_offset;\r\neast_neighbors = bw(east_idx);\r\neast_pairs = [idx(east_neighbors), east_idx(east_neighbors)];\r\n\r\nsouth_idx = idx + south_offset;\r\nsouth_neighbors = bw(south_idx);\r\nsouth_pairs = [idx(south_neighbors), south_idx(south_neighbors)];\r\n\r\nwest_idx = idx + west_offset;\r\nwest_neighbors = bw(west_idx);\r\nwest_pairs = [idx(west_neighbors), west_idx(west_neighbors)];\r\n\r\nall_pairs = [north_pairs; east_pairs; south_pairs; west_pairs]\r\n\r\n\r\n%%\r\n% *Note:* Generally, you need to prepad the matrix to make sure that no\r\n% nonzero elements are on the boundaries. I didn't do that here because my\r\n% sample matrix didn't need it.  Just remember that prepadding changes the\r\n% element locations and the neighbor offset values, so you'll need to\r\n% compensate for that in your own code. The details will vary depending on\r\n% exactly what you are doing with the neighbor values and locations.\r\n%\r\n% For more information about MATLAB indexing, including linear and logical\r\n% indexing, here's a <https:\/\/www.mathworks.com\/company\/newsletters\/articles\/matrix-indexing-in-matlab.html \r\n% MATLAB Digest article> that <https:\/\/blogs.mathworks.com\/loren\/ Loren> and I wrote a few\r\n% years ago.\r\n\r\n##### SOURCE END ##### a8bfe116643b4cbca4a0f1829a3d7d74\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   In response to my last post about connected component labeling algorithms, blog reader JanKees wanted to know how to find neighboring pixel pairs programmatically.  Prompted by this question, I... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/28\/neighbor-indexing\/\">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":[348,330,54,190],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/128"}],"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=128"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/128\/revisions"}],"predecessor-version":[{"id":3524,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/128\/revisions\/3524"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}