{"id":68,"date":"2006-07-07T14:11:04","date_gmt":"2006-07-07T18:11:04","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=68"},"modified":"2019-10-22T13:59:26","modified_gmt":"2019-10-22T17:59:26","slug":"spatial-transformations-translation-confusion","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2006\/07\/07\/spatial-transformations-translation-confusion\/","title":{"rendered":"Spatial transformations: Translation confusion"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>The <a href=\"https:\/\/blogs.mathworks.com\/steve\/?p=63\">last time I wrote about spatial transformations<\/a>, I explained that <tt>imtransform<\/tt> uses the function <tt>findbounds<\/tt> to locate the transformed image in output space.  By default, <tt>imtransform<\/tt> computes an output image grid that is just big enough to capture the output image, wherever it is located.\r\n   <\/p>\r\n   <p>We designed <tt>imtransform<\/tt> this way because we thought it was what users would expect most of the time.  Generally, this default behavior works out\r\n      just fine.  The big exception, though, is when users call <tt>imtransform<\/tt> to apply a pure translation.  Let's try it and see.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">I = imread(<span style=\"color: #A020F0\">'pout.tif'<\/span>);\r\nimshow(I)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/68\/translation_confusion_01.png\"> <p>Now make an affine tform struct representing a pure translation:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">T = [1 0 0; 0 1 0; 50 100 1];\r\ntform = maketform(<span style=\"color: #A020F0\">'affine'<\/span>, T);<\/pre><p>Apply the translation:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">I2 = imtransform(I, tform);<\/pre><p>And compare the two images:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">subplot(1,2,1)\r\nimshow(I)\r\ntitle(<span style=\"color: #A020F0\">'original image'<\/span>)\r\n\r\nsubplot(1,2,2)\r\nimshow(I2)\r\ntitle(<span style=\"color: #A020F0\">'translated image'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/68\/translation_confusion_02.png\"> <p>They're the same!  Hence, the confusion.<\/p>\r\n   <p>Here <tt>imtransform<\/tt> has been a little \"smarter\" than users want.  By automatically adjusting the output-space grid to capture the output image\r\n      wherever it moves, the translation gets removed.\r\n   <\/p>\r\n   <p>There are a couple of things you can do to make this work better.  First, you can ask <tt>imtransform<\/tt> to give you more information about the output space coordinates of the output image, and then you can use this information\r\n      when displaying the image.  Here's how that might work:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[I2,xdata,ydata] = imtransform(I,tform);<\/pre><p><tt>xdata<\/tt> is a two-element vector specifying where the first and last columns of <tt>I2<\/tt> are located in output space.  Similarly, <tt>ydata<\/tt> specifies where the first and last rows are located.  You can pass this information along to the display function, <tt>imshow<\/tt>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">subplot(1,2,1)\r\nimshow(I)\r\naxis <span style=\"color: #A020F0\">on<\/span>\r\naxis([0 400 0 400])\r\n\r\nsubplot(1,2,2)\r\nimshow(I2,<span style=\"color: #A020F0\">'XData'<\/span>,xdata,<span style=\"color: #A020F0\">'YData'<\/span>,ydata)\r\naxis <span style=\"color: #A020F0\">on<\/span>\r\naxis([0 400 0 400])<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/68\/translation_confusion_03.png\"> <p>A second technique is to tell <tt>imtransform<\/tt> what output-space rectangle to use.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">I3 = imtransform(I,tform,<span style=\"color: #A020F0\">'XData'<\/span>,[1 290],<span style=\"color: #A020F0\">'YData'<\/span>,[1 391]);\r\nclf\r\nimshow(I3)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/68\/translation_confusion_04.png\"> <p>If you understand the XData and YData parameters, you can use these techniques separately or in combination to implement whatever\r\n      translation effect you'd like.\r\n   <\/p>\r\n   <p>Since translation is a regular source of calls to tech support, we are exploring ways to alleviate the confusion.  If you\r\n      have suggestions, please leave a blog comment.  Thanks!\r\n   <\/p>\r\n <script language=\"JavaScript\"> \r\n<!--\r\n    function grabCode_68() {\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='68 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 68';\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 2006 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      <\/script>\r\n<noscript>\r\n<em>A JavaScript-enabled browser is required to use the \"Get the MATLAB code\" link.<\/em>\r\n<\/noscript>\r\n<p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_68()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code<\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.2<br><\/p>\r\n<\/div>\r\n<!--\r\n68 ##### SOURCE BEGIN #####\r\n%%\r\n% The <https:\/\/blogs.mathworks.com\/steve\/?p=63 last time I wrote about spatial \r\n% transformations>, I explained that\r\n% <https:\/\/www.mathworks.com\/help\/images\/index.htmlimtransform.html \r\n% |imtransform|> uses the function <https:\/\/www.mathworks.com\/help\/images\/index.htmlfindbounds.html \r\n% |findbounds|> to locate the transformed image\r\n% in output space.  By default, |imtransform| computes an output image grid\r\n% that is just big enough to capture the output image, wherever it is\r\n% located.\r\n%\r\n% We designed |imtransform| this way because we thought it was what users\r\n% would expect most of the time.  Generally, this default behavior works\r\n% out just fine.  The big exception, though, is when users call\r\n% |imtransform|\r\n% to apply a pure translation.  Let's try it and see.\r\n\r\nI = imread('pout.tif');\r\nimshow(I)\r\n\r\n%%\r\n%\r\n% Now make an affine tform struct representing a pure translation:\r\n\r\nT = [1 0 0; 0 1 0; 50 100 1];\r\ntform = maketform('affine', T);\r\n\r\n%%\r\n% Apply the translation:\r\n\r\nI2 = imtransform(I, tform);\r\n\r\n%%\r\n% And compare the two images:\r\n\r\nsubplot(1,2,1)\r\nimshow(I)\r\ntitle('original image')\r\n\r\nsubplot(1,2,2)\r\nimshow(I2)\r\ntitle('translated image')\r\n\r\n%%\r\n% They're the same!  Hence, the confusion.\r\n%\r\n% Here |imtransform| has been a little \"smarter\" than users want.  By\r\n% automatically adjusting the output-space grid to capture the output image\r\n% wherever it moves, the translation gets removed.\r\n%\r\n% There are a couple of things you can do to make\r\n% this work better.  First, you can ask |imtransform| to give you more\r\n% information about the output space coordinates of the output image, and\r\n% then you can use this information when displaying the image.  Here's how\r\n% that might work:\r\n\r\n[I2,xdata,ydata] = imtransform(I,tform);\r\n\r\n%%\r\n% |xdata| is a two-element vector specifying where the first and last\r\n% columns of |I2| are located in output space.  Similarly, |ydata|\r\n% specifies where the first and last rows are located.  You can pass this\r\n% information along to the display function, |imshow|.\r\n\r\nsubplot(1,2,1)\r\nimshow(I)\r\naxis on\r\naxis([0 400 0 400])\r\n\r\nsubplot(1,2,2)\r\nimshow(I2,'XData',xdata,'YData',ydata)\r\naxis on\r\naxis([0 400 0 400])\r\n\r\n%%\r\n% A second technique is to tell |imtransform| what output-space rectangle to\r\n% use.\r\n\r\nI3 = imtransform(I,tform,'XData',[1 290],'YData',[1 391]);\r\nclf\r\nimshow(I3)\r\n\r\n%%\r\n% If you understand the XData and YData parameters, you can use these\r\n% techniques separately or in combination to implement\r\n% whatever translation\r\n% effect you'd like.\r\n%\r\n% Since translation is a regular source of calls to tech support, we are exploring\r\n% ways to alleviate the confusion.  If you have suggestions, please leave a\r\n% blog comment.  Thanks!\r\n\r\n\r\n##### SOURCE END ##### 68\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   The last time I wrote about spatial transformations, I explained that imtransform uses the function findbounds to locate the transformed image in output space.  By default, imtransform computes... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2006\/07\/07\/spatial-transformations-translation-confusion\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[10],"tags":[50,178,76,36,44,62,72,52],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/68"}],"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=68"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/68\/revisions"}],"predecessor-version":[{"id":2193,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/68\/revisions\/2193"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=68"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=68"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=68"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}