{"id":363,"date":"2011-02-17T17:52:03","date_gmt":"2011-02-17T22:52:03","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2011\/02\/17\/pixel-grid\/"},"modified":"2019-10-29T16:19:25","modified_gmt":"2019-10-29T20:19:25","slug":"pixel-grid","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2011\/02\/17\/pixel-grid\/","title":{"rendered":"Pixel grid"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>I started writing a post today about the <tt>ConvexImage<\/tt> property returned by <tt>regionprops<\/tt>. But I got sidetracked along the way, and this post turned into a description of how to overlay a pixel grid on an image.\r\n      (I'll come back to the original <tt>ConvexImage<\/tt> idea in a future post.)\r\n   <\/p>\r\n   <p>Here's what got me sidetracked. I made a tiny little binary image, and then I displayed it with high magnification because\r\n      I wanted to show the individual pixels clearly as square regions.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = [<span style=\"color: #0000FF\">...<\/span>\r\n    0 0 0 1 0 0 0\r\n    0 0 1 0 1 0 0\r\n    0 1 0 0 0 1 0\r\n    1 1 1 1 1 1 1 ];\r\n\r\nimshow(bw, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_01.png\"> <p>Well, that doesn't look good! It's hard to see the individual pixels, and there's a whole row of white pixels at the bottom\r\n      of the image that have disappeared into the background of the page. I decided that it would be nice to see a subtle but visible\r\n      outline around each pixel.  Here's what I have in mind:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_06.png\"> <\/p>\r\n   <p>Let me show you how to do this in a fairly general fashion. When we're done, maybe I'll have something that would be worth\r\n      posting to the <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/\">MATLAB Central File Exchange<\/a>.\r\n   <\/p>\r\n   <p>First, I need to get a handle to the image object because I need some information about the x- and y-coordinates of the pixels.\r\n      I'll use <tt>findobj<\/tt> to find the handle for the image object in the current figure.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">h = findobj(gcf,<span style=\"color: #A020F0\">'type'<\/span>,<span style=\"color: #A020F0\">'image'<\/span>);<\/pre><p>The <tt>XData<\/tt> and <tt>YData<\/tt> properties of the image object determine where the image pixels lie in the axes data space.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">xdata = get(h, <span style=\"color: #A020F0\">'XData'<\/span>)<\/pre><pre style=\"font-style:oblique\">\r\nxdata =\r\n\r\n     1     7\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">ydata = get(h, <span style=\"color: #A020F0\">'YData'<\/span>)<\/pre><pre style=\"font-style:oblique\">\r\nydata =\r\n\r\n     1     4\r\n\r\n<\/pre><p>This means:<\/p>\r\n   <div>\r\n      <ul>\r\n         <li>The x-coordinate of the center of the first image column is 1.0.<\/li>\r\n         <li>The x-coordinate of the center of the last image column is 7.0.<\/li>\r\n         <li>The y-coordinate of the center of the first image row is 1.0.<\/li>\r\n         <li>The y-coordinate of the center of the last image row is 4.0.<\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <p>Let's also grab the number of rows and columns of the image.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">M = size(get(h,<span style=\"color: #A020F0\">'CData'<\/span>), 1);\r\nN = size(get(h,<span style=\"color: #A020F0\">'CData'<\/span>), 2);<\/pre><p><i>Reader challenge: Explain why I didn't use this code:<\/i><\/p><pre>   [M,N] = size(get(h,'CData'));<\/pre><p>Next I want to compute vectors containing the x- and y-locations of the pixel edges.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #0000FF\">if<\/span> M &gt; 1\r\n    pixel_height = diff(ydata) \/ (M-1);\r\n<span style=\"color: #0000FF\">else<\/span>\r\n    <span style=\"color: #228B22\">% Special case. Assume unit height.<\/span>\r\n    pixel_height = 1;\r\n<span style=\"color: #0000FF\">end<\/span>\r\n\r\n<span style=\"color: #0000FF\">if<\/span> N &gt; 1\r\n    pixel_width = diff(xdata) \/ (N-1);\r\n<span style=\"color: #0000FF\">else<\/span>\r\n    <span style=\"color: #228B22\">% Special case. Assume unit width.<\/span>\r\n    pixel_width = 1;\r\n<span style=\"color: #0000FF\">end<\/span>\r\n\r\ny_top = ydata(1) - (pixel_height\/2);\r\ny_bottom = ydata(2) + (pixel_height\/2);\r\ny = linspace(y_top, y_bottom, M+1)<\/pre><pre style=\"font-style:oblique\">\r\ny =\r\n\r\n    0.5000    1.5000    2.5000    3.5000    4.5000\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">x_left = xdata(1) - (pixel_width\/2);\r\nx_right = xdata(2) + (pixel_width\/2);\r\nx = linspace(x_left, x_right, N+1)<\/pre><pre style=\"font-style:oblique\">\r\nx =\r\n\r\n    0.5000    1.5000    2.5000    3.5000    4.5000    5.5000    6.5000    7.5000\r\n\r\n<\/pre><p>Let me pause here and illustrate how we're going to use these numbers. Here's how to plot the vertical edge separating the\r\n      2nd and 3rd columns of pixels.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imshow(bw, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\nplot([x(3) x(3)], [y(1) y(end)], <span style=\"color: #A020F0\">'r'<\/span>, <span style=\"color: #A020F0\">'LineWidth'<\/span>, 2)\r\nhold <span style=\"color: #A020F0\">off<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_02.png\"> <p>We could plot the entire pixel grid by using N+1 vertical lines and M+1 horizontal lines. However, MATLAB graphics performance\r\n      is usually better if you create fewer graphics objects. So I'm going to go to a little more effort in order to create only\r\n      two line objects. One will snake up and down vertically(<tt>xv<\/tt> and <tt>yv<\/tt>); the other will snake left and right horizontally (<tt>xh<\/tt> and <tt>yh<\/tt>).\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">xv = zeros(1, 2*numel(x));\r\nxv(1:2:end) = x;\r\nxv(2:2:end) = x;\r\n\r\nyv = repmat([y(1) ; y(end)], 1, numel(x));\r\nyv(:,2:2:end) = flipud(yv(:,2:2:end));\r\n\r\nxv = xv(:);\r\nyv = yv(:);\r\n\r\nimshow(bw, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\nplot(xv, yv, <span style=\"color: #A020F0\">'r'<\/span>, <span style=\"color: #A020F0\">'LineWidth'<\/span>, 2, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>)\r\nhold <span style=\"color: #A020F0\">off<\/span>\r\ntitle(<span style=\"color: #A020F0\">'Vertical pixel edges'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_03.png\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">yh = zeros(1, 2*numel(y));\r\nyh(1:2:end) = y;\r\nyh(2:2:end) = y;\r\n\r\nxh = repmat([x(1) ; x(end)], 1, numel(y));\r\nxh(:,2:2:end) = flipud(xh(:,2:2:end));\r\n\r\nxh = xh(:);\r\nyh = yh(:);\r\n\r\nimshow(bw, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\nplot(xh, yh, <span style=\"color: #A020F0\">'r'<\/span>, <span style=\"color: #A020F0\">'LineWidth'<\/span>, 2, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>)\r\nhold <span style=\"color: #A020F0\">off<\/span>\r\ntitle(<span style=\"color: #A020F0\">'Horizontal pixel edges'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_04.png\"> <p>To get all edges, superimpose the vertical and horizontal edges. Also, at this point I'm going to start using the low-level\r\n      function <tt>line<\/tt> instead of <tt>plot<\/tt>. This is more robust and cuts out the need to call <tt>hold on<\/tt> and <tt>hold off<\/tt>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">h = imshow(bw, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>);\r\nax = ancestor(h, <span style=\"color: #A020F0\">'axes'<\/span>);\r\nline(<span style=\"color: #A020F0\">'Parent'<\/span>, ax, <span style=\"color: #A020F0\">'XData'<\/span>, xh, <span style=\"color: #A020F0\">'YData'<\/span>, yh, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'Color'<\/span>, <span style=\"color: #A020F0\">'r'<\/span>, <span style=\"color: #A020F0\">'LineWidth'<\/span>, 2, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>);\r\nline(<span style=\"color: #A020F0\">'Parent'<\/span>, ax, <span style=\"color: #A020F0\">'XData'<\/span>, xv, <span style=\"color: #A020F0\">'YData'<\/span>, yv, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'Color'<\/span>, <span style=\"color: #A020F0\">'r'<\/span>, <span style=\"color: #A020F0\">'LineWidth'<\/span>, 2, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>);\r\ntitle(<span style=\"color: #A020F0\">'All pixel edges'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_05.png\"> <p>But what if some of the pixels were red? We wouldn't be able to see the grid. I'm going to use the two-line superposition\r\n      technique that I described way back on <a href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/01\/01\/superimposing-line-plots\/\">New Year's Day, 2007<\/a>, and I'm going to switch to thinner lines using shades of gray.\r\n   <\/p>\r\n   <p>The trick for drawing a line that's guaranteed to be visible against any background is to draw the line twice, using contrasting\r\n      colors and a solid and a dashed line style.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">dark = [.3 .3 .3];\r\nlight = [.8 .8 .8];\r\nh = imshow(bw, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>);\r\nax = ancestor(h, <span style=\"color: #A020F0\">'axes'<\/span>);\r\nline(<span style=\"color: #A020F0\">'Parent'<\/span>, ax, <span style=\"color: #A020F0\">'XData'<\/span>, xh, <span style=\"color: #A020F0\">'YData'<\/span>, yh, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'Color'<\/span>, dark, <span style=\"color: #A020F0\">'LineStyle'<\/span>, <span style=\"color: #A020F0\">'-'<\/span>, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>);\r\nline(<span style=\"color: #A020F0\">'Parent'<\/span>, ax, <span style=\"color: #A020F0\">'XData'<\/span>, xh, <span style=\"color: #A020F0\">'YData'<\/span>, yh, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'Color'<\/span>, light, <span style=\"color: #A020F0\">'LineStyle'<\/span>, <span style=\"color: #A020F0\">'--'<\/span>, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>);\r\nline(<span style=\"color: #A020F0\">'Parent'<\/span>, ax, <span style=\"color: #A020F0\">'XData'<\/span>, xv, <span style=\"color: #A020F0\">'YData'<\/span>, yv, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'Color'<\/span>, dark, <span style=\"color: #A020F0\">'LineStyle'<\/span>, <span style=\"color: #A020F0\">'-'<\/span>, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>);\r\nline(<span style=\"color: #A020F0\">'Parent'<\/span>, ax, <span style=\"color: #A020F0\">'XData'<\/span>, xv, <span style=\"color: #A020F0\">'YData'<\/span>, yv, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'Color'<\/span>, light, <span style=\"color: #A020F0\">'LineStyle'<\/span>, <span style=\"color: #A020F0\">'--'<\/span>, <span style=\"color: #A020F0\">'Clipping'<\/span>, <span style=\"color: #A020F0\">'off'<\/span>);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_06.png\"> <p>OK, readers, it's function design time. I think this technique could be encapsulated into a nice little utility function on\r\n      the File Exchange. But before I go ahead and write it and submit, I'd like to open it up for discussion with you.\r\n   <\/p>\r\n   <p>How about the implementation? The implementation above is basically the first thing I thought of; are there improvements?<\/p>\r\n   <p>How about the function name? I have one in mind, but what would you pick? How about the syntaxes? Input and output arguments?\r\n      Options?\r\n   <\/p>\r\n   <p>Share your thoughts.<\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_a1d616b0089f4c0f925d09a744c57cf2() {\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='a1d616b0089f4c0f925d09a744c57cf2 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' a1d616b0089f4c0f925d09a744c57cf2';\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_a1d616b0089f4c0f925d09a744c57cf2()\"><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.11<br><\/p>\r\n<\/div>\r\n<!--\r\na1d616b0089f4c0f925d09a744c57cf2 ##### SOURCE BEGIN #####\r\n%%\r\n% I started writing a post today about the |ConvexImage| property returned\r\n% by |regionprops|. But I got sidetracked along the way, and this post\r\n% turned into a description of how to overlay a pixel grid on an image.\r\n% (I'll come back to the original |ConvexImage| idea in a future post.)\r\n%\r\n% Here's what got me sidetracked. I made a tiny little binary image, and\r\n% then I displayed it with high magnification because I wanted to show the\r\n% individual pixels clearly as square regions.\r\n\r\nbw = [...\r\n    0 0 0 1 0 0 0\r\n    0 0 1 0 1 0 0\r\n    0 1 0 0 0 1 0\r\n    1 1 1 1 1 1 1 ];\r\n\r\nimshow(bw, 'InitialMagnification', 'fit')\r\n\r\n%%\r\n% Well, that doesn't look good! It's hard to see the individual pixels, and\r\n% there's a whole row of white pixels at the bottom of the image that have\r\n% disappeared into the background of the page. I decided that it would be\r\n% nice to see a subtle but visible outline around each pixel.  Here's what\r\n% I have in mind:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2011\/pixel_grid_06.png>>\r\n%\r\n% Let me show you how to do this in a fairly general fashion. When we're\r\n% done, maybe I'll have something that would be worth posting to the\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/ MATLAB Central File\r\n% Exchange>.\r\n%\r\n% First, I need to get a handle to the image object because I need some\r\n% information about the x- and y-coordinates of the pixels. I'll use\r\n% |findobj| to find the handle for the image object in the current figure.\r\n\r\nh = findobj(gcf,'type','image');\r\n\r\n%%\r\n% The |XData| and |YData| properties of the image object determine where\r\n% the image pixels lie in the axes data space.\r\n\r\nxdata = get(h, 'XData')\r\n\r\n%%\r\n\r\nydata = get(h, 'YData')\r\n\r\n%%\r\n% This means:\r\n%\r\n% * The x-coordinate of the center of the first image column is 1.0.\r\n% * The x-coordinate of the center of the last image column is 7.0.\r\n% * The y-coordinate of the center of the first image row is 1.0.\r\n% * The y-coordinate of the center of the last image row is 4.0.\r\n%\r\n% Let's also grab the number of rows and columns of the image.\r\n\r\nM = size(get(h,'CData'), 1);\r\nN = size(get(h,'CData'), 2);\r\n\r\n%%\r\n% _Reader challenge: Explain why I didn't use this code:_\r\n% \r\n%     [M,N] = size(get(h,'CData'));\r\n%\r\n% Next I want to compute vectors containing the x- and y-locations of the\r\n% pixel edges.\r\n\r\nif M > 1\r\n    pixel_height = diff(ydata) \/ (M-1);\r\nelse\r\n    % Special case. Assume unit height.\r\n    pixel_height = 1;\r\nend\r\n\r\nif N > 1\r\n    pixel_width = diff(xdata) \/ (N-1);\r\nelse\r\n    % Special case. Assume unit width.\r\n    pixel_width = 1;\r\nend\r\n\r\ny_top = ydata(1) - (pixel_height\/2);\r\ny_bottom = ydata(2) + (pixel_height\/2);\r\ny = linspace(y_top, y_bottom, M+1)\r\n\r\n%%\r\nx_left = xdata(1) - (pixel_width\/2);\r\nx_right = xdata(2) + (pixel_width\/2);\r\nx = linspace(x_left, x_right, N+1)\r\n\r\n%%\r\n% Let me pause here and illustrate how we're going to use these numbers.\r\n% Here's how to plot the vertical edge separating the 2nd and 3rd columns\r\n% of pixels.\r\n\r\nimshow(bw, 'InitialMagnification', 'fit')\r\nhold on\r\nplot([x(3) x(3)], [y(1) y(end)], 'r', 'LineWidth', 2)\r\nhold off\r\n\r\n%%\r\n% We could plot the entire pixel grid by using N+1 vertical lines and M+1\r\n% horizontal lines. However, MATLAB graphics performance is usually better\r\n% if you create fewer graphics objects. So I'm going to go to a little more\r\n% effort in order to create only two line objects. One will snake up and\r\n% down vertically(|xv| and |yv|); the other will snake left and right\r\n% horizontally (|xh| and |yh|).\r\n\r\nxv = zeros(1, 2*numel(x));\r\nxv(1:2:end) = x;\r\nxv(2:2:end) = x;\r\n\r\nyv = repmat([y(1) ; y(end)], 1, numel(x));\r\nyv(:,2:2:end) = flipud(yv(:,2:2:end));\r\n\r\nxv = xv(:);\r\nyv = yv(:);\r\n\r\nimshow(bw, 'InitialMagnification', 'fit')\r\nhold on\r\nplot(xv, yv, 'r', 'LineWidth', 2, 'Clipping', 'off')\r\nhold off\r\ntitle('Vertical pixel edges')\r\n\r\n%%\r\nyh = zeros(1, 2*numel(y));\r\nyh(1:2:end) = y;\r\nyh(2:2:end) = y;\r\n\r\nxh = repmat([x(1) ; x(end)], 1, numel(y));\r\nxh(:,2:2:end) = flipud(xh(:,2:2:end));\r\n\r\nxh = xh(:);\r\nyh = yh(:);\r\n\r\nimshow(bw, 'InitialMagnification', 'fit')\r\nhold on\r\nplot(xh, yh, 'r', 'LineWidth', 2, 'Clipping', 'off')\r\nhold off\r\ntitle('Horizontal pixel edges')\r\n\r\n%%\r\n% To get all edges, superimpose the vertical and horizontal edges. Also, at\r\n% this point I'm going to start using the low-level function |line| instead\r\n% of |plot|. This is more robust and cuts out the need to call |hold on|\r\n% and |hold off|.\r\n\r\nh = imshow(bw, 'InitialMagnification', 'fit');\r\nax = ancestor(h, 'axes');\r\nline('Parent', ax, 'XData', xh, 'YData', yh, ...\r\n    'Color', 'r', 'LineWidth', 2, 'Clipping', 'off');\r\nline('Parent', ax, 'XData', xv, 'YData', yv, ...\r\n    'Color', 'r', 'LineWidth', 2, 'Clipping', 'off');\r\ntitle('All pixel edges')\r\n\r\n%%\r\n% But what if some of the pixels were red? We wouldn't be able to see the\r\n% grid. I'm going to use the two-line superposition technique that I\r\n% described way back on\r\n% <https:\/\/blogs.mathworks.com\/steve\/2007\/01\/01\/superimposing-line-plots\/\r\n% New Year's Day, 2007>, and I'm going to switch to thinner lines using\r\n% shades of gray.\r\n%\r\n% The trick for drawing a line that's guaranteed to be visible against any\r\n% background is to draw the line twice, using contrasting colors and a\r\n% solid and a dashed line style.\r\n\r\ndark = [.3 .3 .3];\r\nlight = [.8 .8 .8];\r\nh = imshow(bw, 'InitialMagnification', 'fit');\r\nax = ancestor(h, 'axes');\r\nline('Parent', ax, 'XData', xh, 'YData', yh, ...\r\n    'Color', dark, 'LineStyle', '-', 'Clipping', 'off');\r\nline('Parent', ax, 'XData', xh, 'YData', yh, ...\r\n    'Color', light, 'LineStyle', 'REPLACE_WITH_DASH_DASH', 'Clipping', 'off');\r\nline('Parent', ax, 'XData', xv, 'YData', yv, ...\r\n    'Color', dark, 'LineStyle', '-', 'Clipping', 'off');\r\nline('Parent', ax, 'XData', xv, 'YData', yv, ...\r\n    'Color', light, 'LineStyle', 'REPLACE_WITH_DASH_DASH', 'Clipping', 'off');\r\n\r\n%%\r\n% OK, readers, it's function design time. I think this technique could be\r\n% encapsulated into a nice little utility function on the File Exchange.\r\n% But before I go ahead and write it and submit, I'd like to open it up for\r\n% discussion with you.\r\n%\r\n% How about the implementation? The implementation above is basically the\r\n% first thing I thought of; are there improvements?\r\n%\r\n% How about the function name? I have one in mind, but what would you pick?\r\n% How about the syntaxes? Input and output arguments? Options?\r\n%\r\n% Share your thoughts.\r\n##### SOURCE END ##### a1d616b0089f4c0f925d09a744c57cf2\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   I started writing a post today about the ConvexImage property returned by regionprops. But I got sidetracked along the way, and this post turned into a description of how to overlay a pixel grid... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/02\/17\/pixel-grid\/\">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":[272,695,250,745,172,36,747,743,68,116,190,52,130],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/363"}],"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=363"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/363\/revisions"}],"predecessor-version":[{"id":3721,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/363\/revisions\/3721"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}