{"id":379,"date":"2011-07-19T13:18:38","date_gmt":"2011-07-19T17:18:38","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2011\/07\/19\/jahne-test-pattern-take-2\/"},"modified":"2019-10-29T16:47:03","modified_gmt":"2019-10-29T20:47:03","slug":"jahne-test-pattern-take-2","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2011\/07\/19\/jahne-test-pattern-take-2\/","title":{"rendered":"J\u00e4hne test pattern &#8211; take 2"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>Last week I talked about the so-called J&auml;hne test pattern and how I found a description of it in <i>Practical Handbook on Image Processing for Scientific Applications<\/i>, by Bernd J&auml;hne, CRC Press, 1997. This equation was given in the book:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_eq56929.png\"> <\/p>\r\n   <p>And here's a scan of the test pattern from the book:<\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne-fig1023a.jpg\"> <\/p>\r\n   <p>I showed how to compute a test pattern based just on sine term. Here's the result:<\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/more_on_synthetic_images_01.jpg\"> <\/p>\r\n   <p>You can see that the sine-based test pattern extends all the way to the image corners with no decrease in amplitude, whereas\r\n      the book's test pattern tapers off towards the edges of the image. The book says that \"multiplication by the tanh function\r\n      results in a smooth transition of the ring patterns at the outer edge avoid aliasing problems.\" That made sense to me, but\r\n      I couldn't get my generated image to look like what's in the book.\r\n   <\/p>\r\n   <p>Here's what I tried:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">km = pi;\r\n[x,y] = meshgrid(-200:200);\r\nr = hypot(x,y);\r\nrm = max(r(:));\r\nterm1 = sin( (km * r.^2) \/ (2 * rm) );\r\n\r\nw = 300;\r\nterm2 = 0.5 * tanh((rm - r)\/w) + 0.5;\r\nimshow(term2, [])\r\ntitle(<span style=\"color: #A020F0\">'tanh term'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_01.jpg\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">g = term1 .* term2;\r\nimshow(g,[])<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_02.jpg\"> <p>That's not much of a taper. I couldn't get my test pattern to look like the figure in the book no matter what value I chose\r\n      for <tt>w<\/tt>. I also noticed that the 2nd term goes down to only 0.5, whereas I would expect a tapering function to range between 0.0\r\n      and 1.0. But even when I adjusted the scale and offset of the 2nd term so that it would range between 0.0 and 1.0, I couldn't\r\n      anything that looked like the book's figure.\r\n   <\/p>\r\n   <p>So I took a closer look at the shape of <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_eq19483.png\"> .\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">x = -1:.01:1;\r\nplot(x,tanh(1-abs(x)))<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_03.jpg\"> <p>That didn't make sense to me for a taper function. Based on the figure in the book, I expected the taper function to be flatter\r\n      in the center and to trend more smoothly toward 0 at the edges.\r\n   <\/p>\r\n   <p>Dear reader, I'm feeling a little dense because I never really figured out this puzzle. If I'm missing something here, please\r\n      feel free to tell me in the comments. <em>[UPDATE: Reader Alex H. helped me figure out the problem. See this <a href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/07\/19\/jahne-test-pattern-take-3\/\">follow-up post<\/a>.]<\/em>\r\n   <\/p>\r\n   <p>I thought about constructing another taper function (maybe the <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011a\/toolbox\/signal\/tukeywin.html\">Tukey window?<\/a>), but I'm not sure how necessary this really is. For example, if you're concerned about aliasing effects because of the high\r\n      frequency pattern at the image corners, you could just lower <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_eq10078.png\">  a bit:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">km = 0.5*pi;\r\ng = (sin( (km * r.^2) \/ (2 * rm) ) + 1)\/2;\r\nimshow(g)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_04.jpg\"> <p>I've got one more post planned about this image (fun with bandpass filtering), and then I plan to show you an interesting\r\n      way to generate a checkerboard image (chessboard image?) based on the function <img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne_test_image_tapering_eq70329.png\"> .\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_423fa55b01584a8780c1d25c69d2ba1f() {\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='423fa55b01584a8780c1d25c69d2ba1f ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 423fa55b01584a8780c1d25c69d2ba1f';\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_423fa55b01584a8780c1d25c69d2ba1f()\"><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.12<br><\/p>\r\n<\/div>\r\n<!--\r\n423fa55b01584a8780c1d25c69d2ba1f ##### SOURCE BEGIN #####\r\n%%\r\n% Last week I talked about the so-called J\u00c3\u00a4hne test pattern and how I found\r\n% a description of it in _Practical Handbook on Image Processing for\r\n% Scientific and Technical Applications_, by Bernd J\u00c3\u00a4hne, CRC Press, 1997.\r\n% This equation was given in the book:\r\n% \r\n% $$g({\\bf x}) = g_0 \\sin\\left(\\frac{k_m|{\\bf x}|^2}{2r_m}\\right) \\left[\\frac{1}{2}\r\n% \\tanh\\left(\\frac{r_m-|{\\bf x}|}{w}\\right) + \\frac{1}{2}\\right]$$\r\n%\r\n% And here's a scan of the test pattern from the book:\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2011\/jahne-fig1023a.jpg>>\r\n%\r\n% I showed how to compute a test pattern based just on sine term. Here's the\r\n% result:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2011\/more_on_synthetic_images_01.jpg>>\r\n%\r\n% You can see that the sine-based test pattern extends all the way to the\r\n% image corners with no decrease in amplitude, whereas the book's test\r\n% pattern tapers off towards the edges of the image. The book says that\r\n% \"multiplication by the tanh function results in a smooth transition of\r\n% the ring patterns at the outer edge avoid aliasing problems.\" That made\r\n% sense to me, but I couldn't get my generated image to look like what's in\r\n% the book.\r\n%\r\n% Here's what I tried:\r\n\r\nkm = pi;\r\n[x,y] = meshgrid(-200:200);\r\nr = hypot(x,y);\r\nrm = max(r(:));\r\nterm1 = sin( (km * r.^2) \/ (2 * rm) );\r\n\r\nw = 300;\r\nterm2 = 0.5 * tanh((rm - r)\/w) + 0.5;\r\nimshow(term2, [])\r\ntitle('tanh term')\r\n\r\n%%\r\ng = term1 .* term2;\r\nimshow(g,[])\r\n\r\n%%\r\n% That's not much of a taper. I couldn't get my test pattern to look like\r\n% the figure in the book no matter what value I chose for |w|. I also\r\n% noticed that the 2nd term goes down to only 0.5, whereas I would expect a\r\n% tapering function to range between 0.0 and 1.0. But even when I adjusted\r\n% the scale and offset of the 2nd term so that it would range between 0.0\r\n% and 1.0, I couldn't anything that looked like the book's figure.\r\n%\r\n% So I took a closer look at the shape of $tanh(1-|x|)$.\r\n\r\nx = -1:.01:1;\r\nplot(x,tanh(1-abs(x)))\r\n\r\n%%\r\n% That didn't make sense to me for a taper function. Based on the figure\r\n% in the book, I expected the taper function to be flatter in the center\r\n% and to trend more smoothly toward 0 at the edges.\r\n%\r\n% Dear reader, I'm feeling a little dense because I never really figured\r\n% out this puzzle. If I'm missing something here, please feel free to tell\r\n% me in the comments.\r\n%\r\n% I thought about constructing another taper function (maybe the \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011a\/toolbox\/signal\/tukeywin.html Tukey\r\n% window?>), but I'm not sure how necessary this really is. For example, if\r\n% you're concerned about aliasing effects because of the high frequency\r\n% pattern at the image corners, you could just lower $k_m$ a bit:\r\n\r\nkm = 0.5*pi;\r\ng = (sin( (km * r.^2) \/ (2 * rm) ) + 1)\/2;\r\nimshow(g)\r\n\r\n%%\r\n% I've got one more post planned about this image (fun with bandpass\r\n% filtering), and then I plan to show you an interesting way to generate a\r\n% checkerboard image (chessboard image?) based on the function $(-1)^n$.\r\n##### SOURCE END ##### 423fa55b01584a8780c1d25c69d2ba1f\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   Last week I talked about the so-called J&auml;hne test pattern and how I found a description of it in Practical Handbook on Image Processing for Scientific Applications, by Bernd J&auml;hne, CRC... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/07\/19\/jahne-test-pattern-take-2\/\">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":[208,334,36,122,30,532,68,34,809,52],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/379"}],"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=379"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/379\/revisions"}],"predecessor-version":[{"id":3739,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/379\/revisions\/3739"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=379"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=379"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=379"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}