{"id":12060,"date":"2021-02-09T11:33:31","date_gmt":"2021-02-09T16:33:31","guid":{"rendered":"https:\/\/blogs.mathworks.com\/pick\/?p=12060"},"modified":"2021-02-09T11:33:31","modified_gmt":"2021-02-09T16:33:31","slug":"tracing-the-boundary-of-a-binary-region-in-an-image","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/pick\/2021\/02\/09\/tracing-the-boundary-of-a-binary-region-in-an-image\/","title":{"rendered":"Tracing the boundary of a binary region in an image"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p><a href=\"http:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/911\">Brett<\/a>'s Pick this week is <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/87037-freeman-chain-code\"><tt>Freeman chain code<\/tt><\/a>, by <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/8668631\">Nicolas Douillet<\/a>.<\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#f873440f-63dc-48e1-8f0c-d16eee2c08a6\">A new file prompts a thought experiment<\/a><\/li><li><a href=\"#27e96be9-0415-4050-adb1-826e75385914\">Freeman Chain Code<\/a><\/li><li><a href=\"#b6f827b3-0357-4452-b752-6e25023979d4\">Nicolas's Implementation<\/a><\/li><li><a href=\"#1504b2df-2898-4360-9546-6ae1cc67e3ae\">Image Processing Toolbox<\/a><\/li><li><a href=\"#8d55f955-ad4e-44bc-bd10-d7a0cf6beb87\">How does the timing compare?<\/a><\/li><li><a href=\"#d14ceeca-b76d-408b-9b1b-8c3bd993f70d\">What about more complicated images?<\/a><\/li><li><a href=\"#092a4718-8806-4cb7-a72c-e02dcde0b97f\">A couple of suggestions<\/a><\/li><\/ul><\/div><h4>A new file prompts a thought experiment<a name=\"f873440f-63dc-48e1-8f0c-d16eee2c08a6\"><\/a><\/h4><p>I've never done this before, but I've decided to write about a file that just went live <i>today<\/i> (as I write this)! I was excited to see this image accompanying Nicolas's submission:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode.png\" alt=\"\"> <\/p><p>To be honest, I had never heard of \"Freeman Chain Code,\" but I do <i>a lot<\/i> of image processing, and tracing the boundaries of binary regions often comes in handy--and having options is always a good thing. I'm not unfamiliar with <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/?q=profileid:8668631\">Nicolas's work<\/a>; his 65 File Exchange contributions have been downloaded thousands of times, and have garnered several 5-star ratings. There's lots of good stuff there, and even <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/72669-the-matrix-lab-has-you?s_tid=srchtitle\">one function<\/a> that I'm a bit afraid to run. (Read the 'Overview' and you'll understand.)<\/p><h4>Freeman Chain Code<a name=\"27e96be9-0415-4050-adb1-826e75385914\"><\/a><\/h4><p>Starting, as I typically do, in Wikipedia (I love and regularly support Wikipedia, despite the fact that my kids' teachers won't allow them to use the resource), I did a bit of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Chain_code\">reading about Freeman Chain Code<\/a>. It is essentially a boundary-tracing compression algorithm for binary images.<\/p><h4>Nicolas's Implementation<a name=\"b6f827b3-0357-4452-b752-6e25023979d4\"><\/a><\/h4><p>Nicolas's implementation of the Freeman algorithm does not have any MathWorks' Toolbox dependencies; it runs in core MATLAB. So if you <i>don't<\/i> have the Image Processing Toolbox (IPT), and you need to the trace a solo binary region that has no holes, this function works beautifully:<\/p><pre class=\"language-matlab\"><span class=\"comment\">% ('gear.jpg' is a file that Nicolas shared with his entry.)<\/span>\r\nI = imread(<span class=\"string\">'gear.jpg'<\/span>);\r\nI = imbinarize(I);\r\n[Code, row_idx0, col_idx0] = Freeman_chain_code(I, false);\r\n<span class=\"comment\">% Note: The second input argument is a \"verbose\" flag that triggers the visualization<\/span>\r\n<span class=\"comment\">% of the output. (I suppressed visualization here because the output is shown above.)<\/span>\r\n<\/pre><h4>Image Processing Toolbox<a name=\"1504b2df-2898-4360-9546-6ae1cc67e3ae\"><\/a><\/h4><p>So here's where it gets more interesting. There is, of course, an IPT equivalent way of generating the same information--so I thought I'd do a quick comparison:<\/p><p>Using Image Processing Toolbox functionality:<\/p><pre class=\"language-matlab\">[B,L] = bwboundaries(I, 8);\r\nContour2 = false(size(L));\r\n<span class=\"keyword\">for<\/span> ii = 1:numel(B)\r\n    thisB = B{ii};\r\n    inds = sub2ind(size(L), thisB(:, 1), thisB(:, 2));\r\n    Contour2(inds) = 1;\r\n<span class=\"keyword\">end<\/span>\r\nimshow(Contour2)\r\ntitle(<span class=\"string\">'Using bwboundaries'<\/span>)\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode2.png\" alt=\"\"> <\/p><p>The boundaries <i>look<\/i> identical. (In fact it's easy to verify that, in this case at least, they <i>are<\/i>, in fact, identical.)<\/p><h4>How does the timing compare?<a name=\"8d55f955-ad4e-44bc-bd10-d7a0cf6beb87\"><\/a><\/h4><p>I recommend <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/timeit.html\">timeit<\/a> when you want to accurately evalutate the time it takes a function to run:<\/p><pre class=\"language-matlab\">fcn = @() Freeman_chain_code(I, false);\r\nt_Freeman = timeit(fcn);\r\n<\/pre><p>Defining a function to capture the IPT functionality:<\/p><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> Io = calcBoundaries(I)\r\n[B, L] = bwboundaries(I, 8);\r\nIo = false(size(L));\r\n<span class=\"keyword\">for<\/span> ii = 1:numel(B)\r\n    thisB = B{ii};\r\n    inds = sub2ind(size(L), thisB(:, 1), thisB(:, 2));\r\n    Io(inds) = 1;\r\n<span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p>...we similarly have:<\/p><pre class=\"language-matlab\">fcn = @() calcBoundaries(I);\r\nt_IPT = timeit(fcn);\r\n<\/pre><pre class=\"language-matlab\">&gt;&gt; fprintf(<span class=\"string\">'Freeman: %0.5f sec;\\nIPT: %0.5f sec\\n'<\/span>, t_Freeman, t_IPT)\r\nFreeman: 0.00024 sec;\r\nIPT: 0.00090 sec\r\n<\/pre><p>They're both very fast. Surprisingly, the Freeman boundary detection is even faster than the Toolbox functionality, for this particular image. (It's not validated nearly to the extent that <tt>bwboundaries<\/tt> is.)<\/p><h4>What about more complicated images?<a name=\"d14ceeca-b76d-408b-9b1b-8c3bd993f70d\"><\/a><\/h4><p>But now let's make the situation slightly more complicated. Suppose we have a binary image containing <i>multiple<\/i> regions of interest (ROIs):<\/p><pre class=\"language-matlab\">I = imread(<span class=\"string\">'coins.png'<\/span>);\r\nI = imfill(imbinarize(I), <span class=\"string\">'holes'<\/span>);\r\nFreeman_chain_code(I, true);\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode3.png\" alt=\"\"> <\/p><p>Interesting...the Freeman Chain Code returns only a single contour--for the first region detected (in the MATLAB sense).<\/p><p>Additionally, even if you have a singe region--but that region has one or more holes (i.e., if the <i>Euler number<\/i> of the image is less than 1), Nicolas's function will only capture the <i>outer<\/i> contour of that region!<\/p><pre class=\"language-matlab\">I = false(300);\r\nI(150, 150) = true;\r\nI = bwdist(I);\r\nI = I &gt; 15 &amp; I &lt; 50;\r\n<\/pre><pre class=\"language-matlab\">[~, ~, ~, Contour] = Freeman_chain_code_modified(I, false);\r\n<\/pre><pre class=\"language-matlab\">Contour2 = calcBoundaries(I);\r\nsubplot(2,2,1:2);\r\nimshow(I)\r\ntitle(<span class=\"string\">'Original'<\/span>)\r\nsubplot(2,2,3)\r\nimshow(Contour)\r\ntitle(<span class=\"string\">'Freeman'<\/span>)\r\nsubplot(2,2,4)\r\nimshow(Contour2)\r\ntitle(<span class=\"string\">'bwbounaries'<\/span>)\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode5.png\" alt=\"\"> <\/p><p>I took the liberty of modifying Nicolas's code to accommodate multiple regions. (In doing so, I used some functionality from the IPT!) In the modified version, I wrapped the entire process in a while loop, and set the pixels in each ROI to 0 after processing. I also added the 'Contour' output argument, as I find that it is often the most useful aspect of the boundary-tracing workflow.) In the end:<\/p><pre class=\"language-matlab\">[Code, a, b, Contour] = Freeman_chain_code_modified(I, true);\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode4.png\" alt=\"\"> <\/p><p>But even though the code now accommodates multiple ROIs, it still doesn't work as I need it to on ROIs that contain holes. Moreover, the modified Freeman code is now several times <i>slower<\/i> than the <tt>bwboundaries<\/tt> approach.<\/p><h4>A couple of suggestions<a name=\"092a4718-8806-4cb7-a72c-e02dcde0b97f\"><\/a><\/h4><p>Thanks, Nicolas, for this submission, and for your many others! Your code is well implemented, and quite useful--especially for those who do not have access to the Image Processing Toolbox, and who have simple ROIs to process. I <i>would<\/i> like to see a citation for Freeman's algorithm cited in your work, and I would like to see the 'help' comments fleshed out a bit to assist the users of your file. And finally, it would be useful if you would include the \"Contour\" included in your list of outputs. (Though that's easy enough for anyone to modify.) Nonetheless, really solid work: thought-provoking, and much appreciated!<\/p><p>As always, I welcome your <a href=\"http:\/\/blogs.mathworks.com\/pick\/?p=12060#respond\">thoughts and comments<\/a>.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_ebd75c81e4e745aea41249664cc0c57e() {\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='ebd75c81e4e745aea41249664cc0c57e ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' ebd75c81e4e745aea41249664cc0c57e';\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        copyright = 'Copyright 2021 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 copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\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     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_ebd75c81e4e745aea41249664cc0c57e()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2020b<br><\/p><\/div><!--\r\nebd75c81e4e745aea41249664cc0c57e ##### SOURCE BEGIN #####\r\n%% Tracing the boundary of a binary region in an image\r\n%\r\n% <http:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/911 Brett>'s\r\n% Pick this week is\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/87037-freeman-chain-code |Freeman chain code|>,\r\n% by <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/8668631 Nicolas Douillet>.\r\n%\r\n\r\n%% A new file prompts a thought experiment\r\n% I've never done this before, but I've decided to write about a file that\r\n% just went live _today_ (as I write this)! I was excited to see this image\r\n% accompanying Nicolas's submission:\r\n\r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode.png>>\r\n% \r\n\r\n%%\r\n% To be honest, I had never heard of \"Freeman Chain Code,\" but I do _a lot_\r\n% of image processing, and tracing the boundaries of binary regions often\r\n% comes in handyREPLACE_WITH_DASH_DASHand having options is always a good thing. I'm not unfamiliar with\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/?q=profileid:8668631 Nicolas's work>; \r\n% his 65 File Exchange contributions have been downloaded\r\n% thousands of times, and have garnered several 5-star ratings. There's\r\n% lots of good stuff there, and even <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/72669-the-matrix-lab-has-you?s_tid=srchtitle one function> \r\n% that I'm a bit afraid to run. (Read the 'Overview' and you'll\r\n% understand.)\r\n\r\n%% Freeman Chain Code\r\n% Starting, as I typically do, in Wikipedia (I love and regularly support\r\n% Wikipedia, despite the fact that my kids' teachers won't allow them to\r\n% use the resource), I did a bit of <https:\/\/en.wikipedia.org\/wiki\/Chain_code reading about Freeman Chain Code>. \r\n% It is essentially a boundary-tracing compression algorithm for binary\r\n% images.\r\n\r\n%% Nicolas's Implementation\r\n% Nicolas's implementation of the Freeman algorithm does not have any\r\n% MathWorks' Toolbox dependencies; it runs in core MATLAB. So if you\r\n% _don't_ have the Image Processing Toolbox (IPT), and you need to the trace a\r\n% solo binary region that has no holes, this function works beautifully:\r\n \r\n%%\r\n% \r\n%   % ('gear.jpg' is a file that Nicolas shared with his entry.)\r\n%   I = imread('gear.jpg');\r\n%   I = imbinarize(I);\r\n%   [Code, row_idx0, col_idx0] = Freeman_chain_code(I, false);\r\n%   % Note: The second input argument is a \"verbose\" flag that triggers the visualization \r\n%   % of the output. (I suppressed visualization here because the output is shown above.) \r\n\r\n%% Image Processing Toolbox\r\n% So here's where it gets more interesting. There is, of course, an IPT\r\n% equivalent way of generating the same informationREPLACE_WITH_DASH_DASHso I thought I'd do a\r\n% quick comparison:\r\n%\r\n% Using Image Processing Toolbox functionality:\r\n\r\n%%\r\n% \r\n%   [B,L] = bwboundaries(I, 8);\r\n%   Contour2 = false(size(L));\r\n%   for ii = 1:numel(B)\r\n%       thisB = B{ii};\r\n%       inds = sub2ind(size(L), thisB(:, 1), thisB(:, 2));\r\n%       Contour2(inds) = 1;\r\n%   end\r\n%   imshow(Contour2)\r\n%   title('Using bwboundaries')\r\n\r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode2.png>>\r\n% \r\n\r\n%% \r\n% The boundaries _look_ identical. (In fact it's easy to verify that, in\r\n% this case at least, they _are_, in fact, identical.)\r\n\r\n%% How does the timing compare?\r\n% I recommend <https:\/\/www.mathworks.com\/help\/matlab\/ref\/timeit.html timeit> \r\n% when you want to accurately evalutate the time it takes a function to\r\n% run:\r\n\r\n%%\r\n% \r\n%   fcn = @() Freeman_chain_code(I, false);\r\n%   t_Freeman = timeit(fcn);\r\n\r\n%%\r\n% Defining a function to capture the IPT functionality:\r\n\r\n%%\r\n% \r\n%   function Io = calcBoundaries(I)\r\n%   [B, L] = bwboundaries(I, 8);\r\n%   Io = false(size(L));\r\n%   for ii = 1:numel(B)\r\n%       thisB = B{ii};\r\n%       inds = sub2ind(size(L), thisB(:, 1), thisB(:, 2));\r\n%       Io(inds) = 1;\r\n%   end\r\n%   end\r\n\r\n%%\r\n% ...we similarly have:\r\n\r\n%%\r\n% \r\n%   fcn = @() calcBoundaries(I);\r\n%   t_IPT = timeit(fcn);\r\n% \r\n%   >> fprintf('Freeman: %0.5f sec;\\nIPT: %0.5f sec\\n', t_Freeman, t_IPT)\r\n%   Freeman: 0.00024 sec;\r\n%   IPT: 0.00090 sec\r\n\r\n%% \r\n% They're both very fast. Surprisingly, the Freeman boundary detection is\r\n% even faster than the Toolbox functionality, for this particular image.\r\n% (It's not validated nearly to the extent that |bwboundaries| is.)\r\n%\r\n\r\n%% What about more complicated images?\r\n% But now let's make the situation slightly more complicated. Suppose we\r\n% have a binary image containing _multiple_ regions of interest (ROIs):\r\n\r\n%%\r\n% \r\n%   I = imread('coins.png');\r\n%   I = imfill(imbinarize(I), 'holes');\r\n%   Freeman_chain_code(I, true);\r\n\r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode3.png>>\r\n%\r\n\r\n%%\r\n% Interesting...the Freeman Chain Code returns only a single contourREPLACE_WITH_DASH_DASHfor\r\n% the first region detected (in the MATLAB sense). \r\n%\r\n% Additionally, even if you have a singe regionREPLACE_WITH_DASH_DASHbut that region has one or\r\n% more holes (i.e., if the _Euler number_ of the image is less than 1),\r\n% Nicolas's function will only capture the _outer_ contour of that region!\r\n\r\n%%\r\n% \r\n%   I = false(300);\r\n%   I(150, 150) = true;\r\n%   I = bwdist(I);\r\n%   I = I > 15 & I < 50;\r\n%   \r\n%   [~, ~, ~, Contour] = Freeman_chain_code_modified(I, false);\r\n%   \r\n%   Contour2 = calcBoundaries(I);\r\n%   subplot(2,2,1:2);\r\n%   imshow(I)\r\n%   title('Original')\r\n%   subplot(2,2,3)\r\n%   imshow(Contour)\r\n%   title('Freeman')\r\n%   subplot(2,2,4)\r\n%   imshow(Contour2)\r\n%   title('bwbounaries')\r\n\r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode5.png>>\r\n%\r\n\r\n%% \r\n% I took the liberty of modifying Nicolas's code to accommodate multiple\r\n% regions. (In doing so, I used some functionality from the IPT!) In the\r\n% modified version, I wrapped the entire process in a while loop, and set\r\n% the pixels in each ROI to 0 after processing. I also added the 'Contour'\r\n% output argument, as I find that it is often the most useful aspect of the\r\n% boundary-tracing workflow.) In the end:\r\n\r\n%%\r\n% \r\n%   [Code, a, b, Contour] = Freeman_chain_code_modified(I, true);\r\n\r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode4.png>>\r\n%\r\n\r\n%% \r\n% But even though the code now accommodates multiple ROIs, it still doesn't\r\n% work as I need it to on ROIs that contain holes. Moreover, the modified\r\n% Freeman code is now several times _slower_ than the |bwboundaries|\r\n% approach.\r\n\r\n%% A couple of suggestions\r\n% Thanks, Nicolas, for this submission, and for your many others! Your code\r\n% is well implemented, and quite usefulREPLACE_WITH_DASH_DASHespecially for those who do not\r\n% have access to the Image Processing Toolbox, and who have simple ROIs to\r\n% process. I _would_ like to see a citation for Freeman's algorithm cited\r\n% in your work, and I would like to see the 'help' comments fleshed out a\r\n% bit to assist the users of your file. And finally, it would be useful if\r\n% you would include the \"Contour\" included in your list of outputs. (Though\r\n% that's easy enough for anyone to modify.) Nonetheless, really solid work:\r\n% thought-provoking, and much appreciated!\r\n\r\n%%\r\n% As always, I welcome your\r\n% <http:\/\/blogs.mathworks.com\/pick\/?p=12060#respond thoughts and comments>.\r\n##### SOURCE END ##### ebd75c81e4e745aea41249664cc0c57e\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/FreemanCode.png\" onError=\"this.style.display ='none';\" \/><\/div><p>Brett's Pick this week is Freeman chain code, by Nicolas Douillet.ContentsA new file prompts a thought experimentFreeman Chain CodeNicolas's ImplementationImage Processing ToolboxHow does the timing... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/pick\/2021\/02\/09\/tracing-the-boundary-of-a-binary-region-in-an-image\/\">read more >><\/a><\/p>","protected":false},"author":34,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/12060"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/users\/34"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/comments?post=12060"}],"version-history":[{"count":2,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/12060\/revisions"}],"predecessor-version":[{"id":12074,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/12060\/revisions\/12074"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/media?parent=12060"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/categories?post=12060"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/tags?post=12060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}