(* 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} ] ] ] ) ]