(* by Nasser M. Abbasi, version July 4, 2011 *)

Manipulate[
 
 Row[{
   Dynamic[Refresh[
     
     If[originalImage === 0,
      {
       originalImage = 
        getImage[imageName, imsize, images, keepColor];
       originalImageFFT2 = 
        fft2[originalImage, fftOn3D, True, fftOn3DOriginalImageScale, 
         fftOn3DInverseImageScale, imsizeForDisplay];
       nRowsForRadon = 
        Round[Sqrt[(#[[1]]^2 + #[[2]]^2)]] & @
         ImageDimensions[originalImage]
       }];
     
     lastRadonImage = 
      Radon[originalImage, {n, nRowsForRadon}, {-Pi/2, Pi/2}, 
       Method -> method];
     iradonImage = 
      InverseRadon[lastRadonImage, "Filter" -> inverseMethod, 
       "CutoffFrequency" -> cutOffFrequency];
     displayResult[showSpectrum, iradonImage, originalImageFFT2, 
      imsizeForDisplay, lastRadonImage, imsizeForDisplayOneImage, 
      fftOn3D, fftOn3DOriginalImageScale, fftOn3DInverseImageScale, n],
     
     TrackedSymbols -> {event, method, n, cutOffFrequency, 
       inverseMethod, showSpectrum, fftOn3DInverseImageScale}], 
    SynchronousUpdating -> False 
    ],
   
   Dynamic[Refresh[event = Date[];
     originalImageFFT2 = 
      fft2[originalImage, fftOn3D, True, fftOn3DOriginalImageScale, 
       fftOn3DInverseImageScale, imsizeForDisplay];
     "", TrackedSymbols -> {fftOn3D, fftOn3DOriginalImageScale}]
    ],
   
   Dynamic[Refresh[
     event = Date[];
     originalImage = getImage[imageName, imsize, images, keepColor];
     originalImageFFT2 = 
      fft2[originalImage, fftOn3D, True, fftOn3DOriginalImageScale, 
       fftOn3DInverseImageScale, imsizeForDisplay];
     
     nRowsForRadon = 
      Round[Sqrt[(#[[1]]^2 + #[[2]]^2)]] & @
       ImageDimensions[originalImage];
     lastRadonImage = 
      Radon[originalImage, {n, nRowsForRadon}, {-Pi/2, Pi/2}, 
       Method -> method];
     
     "", TrackedSymbols -> {imageName, keepColor}], 
    SynchronousUpdating -> False]
   }],
 (*--------------------*)
 (* Start of controls  *)
 (*--------------------*)

  Grid[{
   {
    Grid[{
      {
       Control[{{n, 26, Style["n", 11]}, 1, maxNumberOfAngles, 1, 
         ControlType -> Trigger, DisplayAllSteps -> True, 
         ImageSize -> Tiny, AnimationRate -> Automatic, 
         AppearanceElements -> {"ProgressSlider", "ResetPlayButton", 
           "PauseButton", "StepLeftButton", "StepRightButton", 
           "ResetButton"}}]
       },
      
      {Control[{{cutOffFrequency, 0.50, 
          Text@Row[{Subscript[Style["f", Italic, 11], 
             Style["c", Italic, 11]]}]}, .01, 1, 0.01, 
         ImageSize -> Small, Appearance -> "Labeled"}]},
      
      {Control[{ {method, "Radon", 
          Style["Radon", 11]}, (# -> Style[#, 11]) & /@ {"Radon", 
           "Hough"}, ControlType -> PopupMenu, ImageSize -> All}]},
      
      {Control[{ {inverseMethod, # &, Style["inverse", 11]},
         {(1 + Cos[# Pi])/2 & -> Style["Hann", 11],
          1 & -> Style["Rectangular", 11],
          # & -> Style["Ramp-Lak", 11],
          # Sin[# 2 Pi ] & -> Style["Sin Ramp", 11],
          # Cos[# Pi ] & -> Style["Cosine Ramp", 11],
          ((1 - 0.16)/2 - (1/2) Cos[# Pi] + 0.08 Cos[# 2 Pi]) & -> 
           Style["Blackman", 11],
          (0.355768 - 0.487396 Cos[# Pi] + 0.144232 Cos[# 2 Pi]) - 
             0.012604 Cos[# 3 Pi] & -> Style["Nuttal window", 11],
          Sinc[#] & -> Style["Shepp-Logan", 11],
          (.54 + .46 Cos[# Pi]) & -> Style["Hamming", 11],
          Sqrt[1/(1 + #^(2))] & -> Style["Butterworth order 1", 11],
          Sqrt[1/(1 + #^(4))] & -> Style["Butterworth order 2", 11],
          Sqrt[1/(1 + #^(6))] & -> Style["Butterworth order 3", 11],
          None -> Style["No filter", 11]
          }, ControlType -> PopupMenu, ImageSize -> All}]}
      
      }, Alignment -> Left, Spacings -> {0, .4}
     ]
    },
   
   {
    Grid[{
      {
       
       Control[{ {imageName, "head CT", 
          Style["image", 10]}, (# -> Style[#, 10]) & /@ {"head CT", 
           "SheppLogan", "ellipse", "boxed", "Lena", "Mandrill", 
           "ResolutionChart", "2 white spots", "Moon", "small dot", 
           "Numbers", "Clock", "Bricks", "Bubbles2", "Wall", 
           "vertical bar", "noisy image"},
         ControlType -> PopupMenu, ImageSize -> All}
        ],
       
       Control[{ {keepColor, False, Style["color", 10]}, {True, 
          False}, ControlType -> Checkbox }]
       },
      
      {
       Dynamic[Show[If[originalImage === 0,
          {
           
           originalImage = 
            getImage[imageName, imsize, images, keepColor];
           
           nRowsForRadon = 
            Round[Sqrt[(#[[1]]^2 + #[[2]]^2)]] & @
             ImageDimensions[originalImage];
           
           lastRadonImage = 
            Radon[originalImage, {n, nRowsForRadon}, {-Pi/2, Pi/2}, 
             Method -> method];
           
           originalImageFFT2 = 
            fft2[originalImage, fftOn3D, True, 
             fftOn3DOriginalImageScale, fftOn3DInverseImageScale, 
             imsizeForDisplay];
           originalImage
           },
          originalImage
          ], ImageSize -> 180], SynchronousUpdating -> False], 
       SpanFromLeft
       }
      
      }, Alignment -> Center, Spacings -> {.5, .4}]
    },
   
   {
    Grid[{
      {
       Control[{ {showSpectrum, False, Style["show FFT", 10]}, {True, 
          False}, ControlType -> Checkbox }]
       ,
       Control[{ {fftOn3D, False, Style["3D view", 10]}, {True, 
          False}, ControlType -> Checkbox , 
         Enabled -> Dynamic[showSpectrum == True]}]
       }
      }, Spacings -> {4, 0}
     ]
    },
   
   {
    Grid[{
      {
       Style["original image spectrum y scale", 11] 
       },
      {
       Control[{ {fftOn3DOriginalImageScale, .8, ""}, 0.01, 1, .01 , 
         ImageSize -> Small, Enabled -> Dynamic[showSpectrum == True],
          Appearance -> "Labeled"}]
       }
      }, Spacings -> .5, Alignment -> Left
     ]
    },
   
   {
    Grid[{
      {
       Style["inverse radon spectrum y scale", 11] 
       },
      {
       Control[{ {fftOn3DInverseImageScale, .8, ""}, 0.01, 1, .01 , 
         ImageSize -> Small, Enabled -> Dynamic[showSpectrum == True],
          Appearance -> "Labeled"}]
       }
      }, Spacings -> .5, Alignment -> Left
     ]
    }
   }, Spacings -> {1, 1}, Frame -> All, 
  FrameStyle -> Directive[Thickness[.001], Gray]],
 
 {{lastRadonImage, 0}, ControlType -> None},
 {{originalImage, 0}, ControlType -> None},
 {{event, "image"}, ControlType -> None},
 {{originalImageFFT2, 0}, ControlType -> None},
 {{maxNumberOfAngles, 128}, ControlType -> None},
 {{imsize, {256, 256}}, ControlType -> None},
 {{imsizeForDisplay, {200, 200}}, ControlType -> None},
 {{imsizeForDisplayOneImage, {412, 450}}, ControlType -> None},
 {{nRowsForRadon, 0}, ControlType -> None},
 SynchronousUpdating -> False,
 TrackedSymbols -> {None},
 Alignment -> Center,
 ImageMargins -> 0,
 ControlPlacement -> Left,
 AutorunSequencing -> {{1, 30}},
 SynchronousInitialization -> False,
 ImageMargins -> 0,
 FrameMargins -> 1,
 Initialization :> 
  (
   images = {\!\(\*
GraphicsBox[
TagBox[RasterBox[CompressedData["
AAAA7PoCT3gTBA==
"], {{0, 129}, {129, 0}}, {0., 1.},
ColorFunction->GrayLevel],
BoxForm`ImageTag[
         "Real", ColorSpace -> Automatic, Interleaving -> None],
Selectable->False],
BaseStyle->"ImageGraphics",
ImageSizeRaw->{129, 129},
PlotRange->{{0, 129}, {0, 129}}]\), \!\(\*
GraphicsBox[
TagBox[RasterBox[CompressedData["
RYTBsnPq02zV76AwHjI=
"], {{0, 128}, {128, 0}}, {0, 65535},
ColorFunction->GrayLevel],
BoxForm`ImageTag[
         "Bit16", ColorSpace -> Automatic, ImageSize -> All, 
          Interleaving -> None],
Selectable->False],
BaseStyle->"ImageGraphics",
ImageSize->{72., Automatic},
ImageSizeRaw->{128, 128},
PlotRange->{{0, 128}, {0, 128}}]\), \!\(\*
GraphicsBox[
TagBox[RasterBox[CompressedData["
vDAbbUWy4oVggSUQpRw45vnj2t9sGf3CivzYcmme8/i/IoEzDQ==
"], {{0, 235}, {
          235, 0}}, {0, 255},
ColorFunction->RGBColor],
BoxForm`ImageTag["Byte", ColorSpace -> "RGB", Interleaving -> True],
Selectable->False],
BaseStyle->"ImageGraphics",
ImageSize->Automatic,
ImageSizeRaw->{235, 235},
PlotRange->{{0, 235}, {0, 235}}]\), \!\(\*
GraphicsBox[
TagBox[RasterBox[CompressedData["
9rJarWzaOT4+Pjo6Go1Gtl5iOQ0AAAAAAADs4n+2oMOu
"], {{0, 432}, {194, 
          0}}, {0, 255},
ColorFunction->RGBColor],
BoxForm`ImageTag["Byte", ColorSpace -> "RGB", Interleaving -> True],
Selectable->False],
BaseStyle->"ImageGraphics",
ImageSizeRaw->{194, 432},
PlotRange->{{0, 194}, {0, 432}}]\), \!\(\*
GraphicsBox[
TagBox[RasterBox[CompressedData["
bgAp3QBSaTcAAAAAAAAAWM9/AI3xp00=
"], {{0, 359}, {360, 0}}, {0, 255},
ColorFunction->RGBColor],
BoxForm`ImageTag["Byte", ColorSpace -> "RGB", Interleaving -> True],
Selectable->False],
BaseStyle->"ImageGraphics",
ImageSize->{48., Automatic},
ImageSizeRaw->{360, 359},
PlotRange->{{0, 360}, {0, 359}}]\), \!\(\*
GraphicsBox[{
{GrayLevel[1], RectangleBox[{-4, -10}, {4, 10}]}, 
         RectangleBox[{-1, -10}, {1, 10}]}]\), \!\(\*
GraphicsBox[{
{GrayLevel[0], RectangleBox[{-20, -20}, {20, 20}]}, 
{GrayLevel[1], RectangleBox[{-10, -10}, {10, 10}]}, 
{GrayLevel[0.5], RectangleBox[{-5, -2}, {5, 2}]}},
ImageSize->{64., Automatic}]\), \!\(\*
GraphicsBox[
TagBox[RasterBox[CompressedData["
Zd/0xs0fR4ERWcpudTHoS/Pzp2LGkeD/AUyacgw=
"], {{0, 160}, {160, 0}}, {
          0., 1.},
ColorFunction->RGBColor],
BoxForm`ImageTag["Real", ColorSpace -> "RGB", Interleaving -> False],
Selectable->False],
BaseStyle->"ImageGraphics",
ImageSize->{76., Automatic},
ImageSizeRaw->{160, 160},
PlotRange->{{0, 160}, {0, 160}}]\)};
   (*--------------------*)
   (*  read image        *)
   (*--------------------*)

      getImage[imageName_String, imsize_, images_, keepColor_] := 
    Module[{returnedImage},
     
     Which[imageName == "2 white spots", returnedImage = images[[1]],
      imageName == "head CT", returnedImage = images[[2]],
      imageName == "SheppLogan", returnedImage = images[[3]],
      imageName == "ellipse", returnedImage = images[[4]],
      imageName == "small dot", returnedImage = images[[5]],
      imageName == "vertical bar", returnedImage = images[[6]],
      imageName == "boxed", returnedImage = images[[7]],
      imageName == "noisy image", returnedImage = images[[8]],
      
      imageName == "Bricks", 
      returnedImage = ExampleData[{"Texture", imageName}],
      imageName == "Bubbles2", 
      returnedImage = ExampleData[{"Texture", imageName}],
      imageName == "Wall", 
      returnedImage = ExampleData[{"Texture", imageName}],
      
      True, returnedImage = ExampleData[{"TestImage", imageName}]
      ];
     
     (*Only use one channel to reduce memory on radon/
     inverse radon use later on*)
     (*unless user wants color*)
   
       If[ ImageChannels[returnedImage] == 3 && Not[keepColor],
      returnedImage = Image[ImageData[returnedImage][[All, All, 1]]]
      ];
     
     (*reduce the size to reduce memory need for future operations*)
 
         ImageResize[returnedImage, imsize]
     
     ];
   
   (*--------------------*)
   (* find FFT2          *)
   (*--------------------*)

      fft2[theImage_, fftOn3D_, isOriginal_, yForOriginal_, 
     yForRadon_, imsizeForDisplay_] := 
    Module[{data, i, j, nRow, nCol, fw, tb, scale, abs},
     
     data = 
      If[ImageChannels[theImage] == 3, 
       ImageData[theImage][[All, All, 1]], 
       ImageData[theImage][[All, All]]];
     
     (*center image before fft*)
     {nRow, nCol} = 
      Dimensions[data];
     tb = N@Table[i + j, {i, nRow}, {j, nCol}];
     data = data*Power[-1, tb];
     
     fw = Fourier[data, FourierParameters -> {1, 1}];
     
     scale = If[fftOn3D,
       1,
       If[isOriginal, 100*yForOriginal, 10*yForRadon ]
       ];
     
     abs = scale*Log[1 + Abs@fw];
     
     If[fftOn3D,
      Image@
       ListPlot3D[abs, MaxPlotPoints -> 60, 
        ImageSize -> imsizeForDisplay, 
        PlotRange -> {All, 
          All, {0, 
           If[isOriginal, yForOriginal Max[abs], 
            yForRadon Max[abs]]}}, ImageMargins -> 2, 
        ImagePadding -> 20],
      
      ImageAdjust[Image[abs]]
      
      ]
     ];
   
   (*--------------------*)
   (* displayResult      *)
   (*--------------------*)

      displayResult[showSpectrum_, iradonImage_, originalImageFFT2_, 
     imsizeForDisplay_, lastRadonImage_, imsizeForDisplayOneImage_, 
     fftOn3D_, fftOn3DOriginalImageScale_, fftOn3DInverseImageScale_, 
     n_] := Module[{},
     
     If[showSpectrum,
      Grid[{
        {
         Text@
          Row[{Style["number of projection angles = ", 12], 
            Style[n, 12]}], SpanFromLeft
         },
        {
         Grid[{
           
           {
            
            Show[ImageAdjust[iradonImage], 
             ImageSize -> imsizeForDisplay],
            
            Show[ImageAdjust[
              ImageResize[lastRadonImage, imsizeForDisplay]]]},
           
           {Text[Style["inverse Radon image", 12]], 
            Text[Style["Radon image", 12]]}
           }, Frame -> None, 
          FrameStyle -> Directive[Thickness[.001], Gray], 
          Alignment -> Center, Spacings -> {.6, .3}]
         }
        ,
        {
         Grid[{
           {Show[
             fft2[iradonImage, fftOn3D, False, 
              fftOn3DOriginalImageScale, fftOn3DInverseImageScale, 
              imsizeForDisplay], ImageSize -> imsizeForDisplay], 
            Show[originalImageFFT2, ImageSize -> imsizeForDisplay]},
           {Text[Style["inverse Radon magnitude spectrum", 12]], 
            Text[Style["original image magnitude spectrum", 12]]}
           }, Frame -> None, 
          FrameStyle -> Directive[Thickness[.001], Gray],
          
          Alignment -> Center, Spacings -> {.6, .3}
          ]
         }
        
        }, Alignment -> Center, Spacings -> {0, .5}
       ],
      Grid[{
        {
         Text@
          Row[{Style["number of projection angles = ", 12], 
            Style[n, 12]}]
         },
        {
         Show[ImageAdjust[iradonImage], 
          ImageSize -> imsizeForDisplayOneImage]
         },
        {
         Text[Style["inverse Radon image", 12]]
         }
        }, Alignment -> Center, Spacings -> {0.6, 0.3}
       ]
      ]
     ]
   
   )
 
 ]