{"id":301,"date":"2009-11-20T19:56:36","date_gmt":"2009-11-21T00:56:36","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2009\/11\/20\/extracting-dot-locations-from-a-graphic\/"},"modified":"2019-10-29T08:06:17","modified_gmt":"2019-10-29T12:06:17","slug":"extracting-dot-locations-from-a-graphic","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2009\/11\/20\/extracting-dot-locations-from-a-graphic\/","title":{"rendered":"Extracting dot locations from a graphic"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>I was looking at the image below on a <a href=\"http:\/\/cgm.cs.mcgill.ca\/~godfried\/teaching\/projects97\/belair\/alpha.html\">web page<\/a> recently and I decided to extract the locations of all the dots. I thought the procedure might make a nice little end-of-the-week\r\n      how-to post.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #228B22\">% Did you know that imread can read directly from a URL?<\/span>\r\nurl = <span style=\"color: #A020F0\">'http:\/\/cgm.cs.mcgill.ca\/~godfried\/teaching\/projects97\/belair\/example1.gif'<\/span>;\r\n[X, map] = imread(url);\r\nimshow(X, map)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/dot_locations_01.png\"> <p>First question to answer: What is the index of the color used for the dots? One easy way to go is to use <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/imtool.html\"><tt>imtool<\/tt><\/a>.\r\n   <\/p>\r\n   <p>Here's a screenshot:<\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/imtool-screen-shot.png\"> <\/p>\r\n   <p>As you can see, when I placed the mouse pointer over the center of one of the dots, the pixel info display at the lower left\r\n      showed that the index value was 1, and the corresponding colormap color was [1.00, 0.78, 0.00].\r\n   <\/p>\r\n   <p>Now that we know the index value, we can easily make a binary image of just the interior of the dots.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = X == 1;\r\nimshow(bw)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/dot_locations_02.png\"> <p>Now we can compute the centroids of the dots.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">s = regionprops(bw, <span style=\"color: #A020F0\">'Centroid'<\/span>)<\/pre><pre style=\"font-style:oblique\">\r\ns = \r\n\r\n122x1 struct array with fields:\r\n    Centroid\r\n\r\n<\/pre><p>The line above is a new syntax for <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/regionprops.html\"><tt>regionprops<\/tt><\/a> that we introduced earlier this year in R2009a.  Previously, you always had to compute a label matrix first using <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/bwlabel.html\"><tt>bwlabel<\/tt><\/a> and then pass that label matrix to <tt>regionprops<\/tt>.  Now <tt>regionprops<\/tt> can do this computation directly on the binary image.  Since the label matrix is not computed, this new syntax uses less\r\n      memory and usually runs faster than the old version.\r\n   <\/p>\r\n   <p>For those of you using an older version, do this instead:<\/p><pre> L = bwlabel(bw);\r\n s = regionprops(L, 'Centroid');<\/pre><p>To show the results, display the image and then superimpose the centroid locations.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imshow(X, map)\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\n<span style=\"color: #0000FF\">for<\/span> k = 1:numel(s)\r\n    centroid_k = s(k).Centroid;\r\n    plot(centroid_k(1), centroid_k(2), <span style=\"color: #A020F0\">'b.'<\/span>);\r\n<span style=\"color: #0000FF\">end<\/span>\r\nhold <span style=\"color: #A020F0\">off<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/dot_locations_03.png\"> <p>Hmm. It looks we got only one dot at some of those locations.  Use the zoom button on the Figure Window toolbar to zoom in.\r\n       Or you can do it noninteractively:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">axis([50 100 0 50])<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/dot_locations_04.png\"> <p>Yep. For overlapping circles, we are only getting one location. The reason is that the interiors of the overlapping circles\r\n      are 8-connected to each other, so they are regarded by <tt>regionprops<\/tt> as single regions.  To get two locations for these overlapping circles, we have to label the regions using 4-connectivity\r\n      instead of 8-connectivity.\r\n   <\/p>\r\n   <p>To do this we have to compute the connected components in a separate step and then call <tt>regionprops<\/tt>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">cc = bwconncomp(bw, 4);\r\ns = regionprops(cc, <span style=\"color: #A020F0\">'Centroid'<\/span>);<\/pre><p><a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/bwconncomp.html\"><tt>bwconncomp<\/tt><\/a> is also new to R2009a. Users of R2008b and earlier can do:\r\n   <\/p><pre> L = bwlabel(bw, 4);\r\n s = regionprops(L, 'Centroid');<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imshow(X, map)\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\n<span style=\"color: #0000FF\">for<\/span> k = 1:numel(s)\r\n    centroid_k = s(k).Centroid;\r\n    plot(centroid_k(1), centroid_k(2), <span style=\"color: #A020F0\">'b.'<\/span>);\r\n<span style=\"color: #0000FF\">end<\/span>\r\nhold <span style=\"color: #A020F0\">off<\/span>\r\naxis([50 100 0 50])<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/dot_locations_05.png\"> <p>Much better.<\/p>\r\n   <p>This little example showed several useful things:<\/p>\r\n   <div>\r\n      <ul>\r\n         <li>Reading an image directly from a URL<\/li>\r\n         <li>Using <tt>imtool<\/tt> to inspect individual pixel values\r\n         <\/li>\r\n         <li>Using the new, more efficient syntax of <tt>regionprops<\/tt><\/li>\r\n         <li>Using the new <tt>bwconncomp<\/tt><\/li>\r\n         <li>Superimposing plots on an image<\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <p>Have a happy weekend!<\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_e948b6c7c06443fb92b2e2de280bed8f() {\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='e948b6c7c06443fb92b2e2de280bed8f ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' e948b6c7c06443fb92b2e2de280bed8f';\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 = '';\r\n        copyright = 'Copyright 2009 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_e948b6c7c06443fb92b2e2de280bed8f()\"><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.9<br><\/p>\r\n<\/div>\r\n<!--\r\ne948b6c7c06443fb92b2e2de280bed8f ##### SOURCE BEGIN #####\r\n%%\r\n% I was looking at the image below on a \r\n% <http:\/\/cgm.cs.mcgill.ca\/~godfried\/teaching\/projects97\/belair\/alpha.html \r\n% web page> recently and I decided to\r\n% extract the locations of all the dots. I thought the procedure might make a\r\n% nice little end-of-the-week how-to post.\r\n\r\n% Did you know that imread can read directly from a URL?\r\nurl = 'http:\/\/cgm.cs.mcgill.ca\/~godfried\/teaching\/projects97\/belair\/example1.gif';\r\n[X, map] = imread(url);\r\nimshow(X, map)\r\n\r\n%%\r\n% First question to answer: What is the index of the color used for the dots?\r\n% One easy way to go is to use \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/imtool.html |imtool|>.\r\n%\r\n% Here's a screenshot:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2009\/imtool-screen-shot.png>>\r\n%\r\n% As you can see, when I placed the mouse pointer over the center of one of the\r\n% dots, the pixel info display at the lower left showed that the index value was\r\n% 1, and the corresponding colormap color was [1.00, 0.78, 0.00].\r\n%\r\n% Now that we know the index value, we can easily make a binary image of just the interior\r\n% of the dots.\r\n\r\nbw = X == 1;\r\nimshow(bw)\r\n\r\n%%\r\n% Now we can compute the centroids of the dots.\r\n\r\ns = regionprops(bw, 'Centroid')\r\n\r\n%%\r\n% The line above is a new syntax for \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/regionprops.html \r\n% |regionprops|> that we introduced earlier\r\n% this year in R2009a.  Previously, you always had to compute a label matrix\r\n% first using \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/bwlabel.html \r\n% |bwlabel|> and then pass that label matrix to |regionprops|.  Now\r\n% |regionprops| can do this computation directly on the binary image.  Since the\r\n% label matrix is not computed, this new syntax uses less memory and usually\r\n% runs faster than the old version.\r\n%\r\n% For those of you using an older version, do this instead:\r\n%\r\n%   L = bwlabel(bw);\r\n%   s = regionprops(L, 'Centroid');\r\n%\r\n% To show the results, display the image and then superimpose the centroid\r\n% locations.\r\n\r\nimshow(X, map)\r\nhold on\r\nfor k = 1:numel(s)\r\n    centroid_k = s(k).Centroid;\r\n    plot(centroid_k(1), centroid_k(2), 'b.');\r\nend\r\nhold off\r\n\r\n%%\r\n% Hmm. It looks we got only one dot at some of those locations.  Use the zoom\r\n% button on the Figure Window toolbar to zoom in.  Or you can do it\r\n% noninteractively:\r\n\r\naxis([50 100 0 50])\r\n\r\n%%\r\n% Yep. For overlapping circles, we are only getting one location. The reason is\r\n% that the interiors of the overlapping circles are 8-connected to each other,\r\n% so they are regarded by |regionprops| as single regions.  To get two locations\r\n% for these overlapping circles, we have to label the regions using\r\n% 4-connectivity instead of 8-connectivity.\r\n%\r\n% To do this we have to compute the connected components in a separate step and\r\n% then call |regionprops|.\r\n\r\ncc = bwconncomp(bw, 4);\r\ns = regionprops(cc, 'Centroid');\r\n\r\n%%\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2009b\/toolbox\/images\/bwconncomp.html \r\n% |bwconncomp|> is also new to R2009a. Users of R2008b and earlier can do:\r\n%\r\n%   L = bwlabel(bw, 4);\r\n%   s = regionprops(L, 'Centroid');\r\n\r\nimshow(X, map)\r\nhold on\r\nfor k = 1:numel(s)\r\n    centroid_k = s(k).Centroid;\r\n    plot(centroid_k(1), centroid_k(2), 'b.');\r\nend\r\nhold off\r\naxis([50 100 0 50])\r\n\r\n%%\r\n% Much better.\r\n%\r\n% This little example showed several useful things:\r\n%\r\n% * Reading an image directly from a URL\r\n% * Using |imtool| to inspect individual pixel values\r\n% * Using the new, more efficient syntax of |regionprops|\r\n% * Using the new |bwconncomp|\r\n% * Superimposing plots on an image\r\n%\r\n% Have a happy weekend!\r\n\r\n##### SOURCE END ##### e948b6c7c06443fb92b2e2de280bed8f\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   I was looking at the image below on a web page recently and I decided to extract the locations of all the dots. I thought the procedure might make a nice little end-of-the-week\r\n      how-to... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/11\/20\/extracting-dot-locations-from-a-graphic\/\">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":[50,561,166,90,76,36,180,162,68,168],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/301"}],"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=301"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/301\/revisions"}],"predecessor-version":[{"id":3661,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/301\/revisions\/3661"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=301"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=301"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=301"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}