ali_m

fastaniso

Sep 3rd, 2012 (edited)
13,197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.96 KB | None | 0 0
  1. # Original work: Copyright (c) 1995-2012 Peter Kovesi pk@peterkovesi.com
  2. # Modified work: Copyright (c) 2012 Alistair Muldal
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in all
  12. # copies or substantial portions of the Software.
  13. #
  14. # The software is provided "as is", without warranty of any kind, express or
  15. # implied, including but not limited to the warranties of merchantability,
  16. # fitness for a particular purpose and noninfringement. In no event shall the
  17. # authors or copyright holders be liable for any claim, damages or other
  18. # liability, whether in an action of contract, tort or otherwise, arising from,
  19. # out of or in connection with the software or the use or other dealings in the
  20. # software.
  21.  
  22. import numpy as np
  23. import warnings
  24.  
  25. def anisodiff(img,niter=1,kappa=50,gamma=0.1,step=(1.,1.),option=1,ploton=False):
  26.     """
  27.     Anisotropic diffusion.
  28.  
  29.     Usage:
  30.     imgout = anisodiff(im, niter, kappa, gamma, option)
  31.  
  32.     Arguments:
  33.             img    - input image
  34.             niter  - number of iterations
  35.             kappa  - conduction coefficient 20-100 ?
  36.             gamma  - max value of .25 for stability
  37.             step   - tuple, the distance between adjacent pixels in (y,x)
  38.             option - 1 Perona Malik diffusion equation No 1
  39.                      2 Perona Malik diffusion equation No 2
  40.             ploton - if True, the image will be plotted on every iteration
  41.  
  42.     Returns:
  43.             imgout   - diffused image.
  44.  
  45.     kappa controls conduction as a function of gradient.  If kappa is low
  46.     small intensity gradients are able to block conduction and hence diffusion
  47.     across step edges.  A large value reduces the influence of intensity
  48.     gradients on conduction.
  49.  
  50.     gamma controls speed of diffusion (you usually want it at a maximum of
  51.     0.25)
  52.  
  53.     step is used to scale the gradients in case the spacing between adjacent
  54.     pixels differs in the x and y axes
  55.  
  56.     Diffusion equation 1 favours high contrast edges over low contrast ones.
  57.     Diffusion equation 2 favours wide regions over smaller ones.
  58.  
  59.     Reference:
  60.     P. Perona and J. Malik.
  61.     Scale-space and edge detection using ansotropic diffusion.
  62.     IEEE Transactions on Pattern Analysis and Machine Intelligence,
  63.     12(7):629-639, July 1990.
  64.  
  65.     Original MATLAB code by Peter Kovesi  
  66.     School of Computer Science & Software Engineering
  67.     The University of Western Australia
  68.     pk @ csse uwa edu au
  69.     <http://www.csse.uwa.edu.au>
  70.  
  71.     Translated to Python and optimised by Alistair Muldal
  72.     Department of Pharmacology
  73.     University of Oxford
  74.     <alistair.muldal@pharm.ox.ac.uk>
  75.  
  76.     June 2000  original version.      
  77.     March 2002 corrected diffusion eqn No 2.
  78.     July 2012 translated to Python
  79.     """
  80.  
  81.     # ...you could always diffuse each color channel independently if you
  82.     # really want
  83.     if img.ndim == 3:
  84.         warnings.warn("Only grayscale images allowed, converting to 2D matrix")
  85.         img = img.mean(2)
  86.  
  87.     # initialize output array
  88.     img = img.astype('float32')
  89.     imgout = img.copy()
  90.  
  91.     # initialize some internal variables
  92.     deltaS = np.zeros_like(imgout)
  93.     deltaE = deltaS.copy()
  94.     NS = deltaS.copy()
  95.     EW = deltaS.copy()
  96.     gS = np.ones_like(imgout)
  97.     gE = gS.copy()
  98.  
  99.     # create the plot figure, if requested
  100.     if ploton:
  101.         import pylab as pl
  102.         from time import sleep
  103.  
  104.         fig = pl.figure(figsize=(20,5.5),num="Anisotropic diffusion")
  105.         ax1,ax2 = fig.add_subplot(1,2,1),fig.add_subplot(1,2,2)
  106.  
  107.         ax1.imshow(img,interpolation='nearest')
  108.         ih = ax2.imshow(imgout,interpolation='nearest',animated=True)
  109.         ax1.set_title("Original image")
  110.         ax2.set_title("Iteration 0")
  111.  
  112.         fig.canvas.draw()
  113.  
  114.     for ii in xrange(niter):
  115.  
  116.         # calculate the diffs
  117.         deltaS[:-1,: ] = np.diff(imgout,axis=0)
  118.         deltaE[: ,:-1] = np.diff(imgout,axis=1)
  119.  
  120.         # conduction gradients (only need to compute one per dim!)
  121.         if option == 1:
  122.             gS = np.exp(-(deltaS/kappa)**2.)/step[0]
  123.             gE = np.exp(-(deltaE/kappa)**2.)/step[1]
  124.         elif option == 2:
  125.             gS = 1./(1.+(deltaS/kappa)**2.)/step[0]
  126.             gE = 1./(1.+(deltaE/kappa)**2.)/step[1]
  127.  
  128.         # update matrices
  129.         E = gE*deltaE
  130.         S = gS*deltaS
  131.  
  132.         # subtract a copy that has been shifted 'North/West' by one
  133.         # pixel. don't as questions. just do it. trust me.
  134.         NS[:] = S
  135.         EW[:] = E
  136.         NS[1:,:] -= S[:-1,:]
  137.         EW[:,1:] -= E[:,:-1]
  138.  
  139.         # update the image
  140.         imgout += gamma*(NS+EW)
  141.  
  142.         if ploton:
  143.             iterstring = "Iteration %i" %(ii+1)
  144.             ih.set_data(imgout)
  145.             ax2.set_title(iterstring)
  146.             fig.canvas.draw()
  147.             # sleep(0.01)
  148.  
  149.     return imgout
  150.  
  151. def anisodiff3(stack,niter=1,kappa=50,gamma=0.1,step=(1.,1.,1.),option=1,ploton=False):
  152.     """
  153.     3D Anisotropic diffusion.
  154.  
  155.     Usage:
  156.     stackout = anisodiff(stack, niter, kappa, gamma, option)
  157.  
  158.     Arguments:
  159.             stack  - input stack
  160.             niter  - number of iterations
  161.             kappa  - conduction coefficient 20-100 ?
  162.             gamma  - max value of .25 for stability
  163.             step   - tuple, the distance between adjacent pixels in (z,y,x)
  164.             option - 1 Perona Malik diffusion equation No 1
  165.                      2 Perona Malik diffusion equation No 2
  166.             ploton - if True, the middle z-plane will be plotted on every
  167.                  iteration
  168.  
  169.     Returns:
  170.             stackout   - diffused stack.
  171.  
  172.     kappa controls conduction as a function of gradient.  If kappa is low
  173.     small intensity gradients are able to block conduction and hence diffusion
  174.     across step edges.  A large value reduces the influence of intensity
  175.     gradients on conduction.
  176.  
  177.     gamma controls speed of diffusion (you usually want it at a maximum of
  178.     0.25)
  179.  
  180.     step is used to scale the gradients in case the spacing between adjacent
  181.     pixels differs in the x,y and/or z axes
  182.  
  183.     Diffusion equation 1 favours high contrast edges over low contrast ones.
  184.     Diffusion equation 2 favours wide regions over smaller ones.
  185.  
  186.     Reference:
  187.     P. Perona and J. Malik.
  188.     Scale-space and edge detection using ansotropic diffusion.
  189.     IEEE Transactions on Pattern Analysis and Machine Intelligence,
  190.     12(7):629-639, July 1990.
  191.  
  192.     Original MATLAB code by Peter Kovesi  
  193.     School of Computer Science & Software Engineering
  194.     The University of Western Australia
  195.     pk @ csse uwa edu au
  196.     <http://www.csse.uwa.edu.au>
  197.  
  198.     Translated to Python and optimised by Alistair Muldal
  199.     Department of Pharmacology
  200.     University of Oxford
  201.     <alistair.muldal@pharm.ox.ac.uk>
  202.  
  203.     June 2000  original version.      
  204.     March 2002 corrected diffusion eqn No 2.
  205.     July 2012 translated to Python
  206.     """
  207.  
  208.     # ...you could always diffuse each color channel independently if you
  209.     # really want
  210.     if stack.ndim == 4:
  211.         warnings.warn("Only grayscale stacks allowed, converting to 3D matrix")
  212.         stack = stack.mean(3)
  213.  
  214.     # initialize output array
  215.     stack = stack.astype('float32')
  216.     stackout = stack.copy()
  217.  
  218.     # initialize some internal variables
  219.     deltaS = np.zeros_like(stackout)
  220.     deltaE = deltaS.copy()
  221.     deltaD = deltaS.copy()
  222.     NS = deltaS.copy()
  223.     EW = deltaS.copy()
  224.     UD = deltaS.copy()
  225.     gS = np.ones_like(stackout)
  226.     gE = gS.copy()
  227.     gD = gS.copy()
  228.  
  229.     # create the plot figure, if requested
  230.     if ploton:
  231.         import pylab as pl
  232.         from time import sleep
  233.  
  234.         showplane = stack.shape[0]//2
  235.  
  236.         fig = pl.figure(figsize=(20,5.5),num="Anisotropic diffusion")
  237.         ax1,ax2 = fig.add_subplot(1,2,1),fig.add_subplot(1,2,2)
  238.  
  239.         ax1.imshow(stack[showplane,...].squeeze(),interpolation='nearest')
  240.         ih = ax2.imshow(stackout[showplane,...].squeeze(),interpolation='nearest',animated=True)
  241.         ax1.set_title("Original stack (Z = %i)" %showplane)
  242.         ax2.set_title("Iteration 0")
  243.  
  244.         fig.canvas.draw()
  245.  
  246.     for ii in xrange(niter):
  247.  
  248.         # calculate the diffs
  249.         deltaD[:-1,: ,:  ] = np.diff(stackout,axis=0)
  250.         deltaS[:  ,:-1,: ] = np.diff(stackout,axis=1)
  251.         deltaE[:  ,: ,:-1] = np.diff(stackout,axis=2)
  252.  
  253.         # conduction gradients (only need to compute one per dim!)
  254.         if option == 1:
  255.             gD = np.exp(-(deltaD/kappa)**2.)/step[0]
  256.             gS = np.exp(-(deltaS/kappa)**2.)/step[1]
  257.             gE = np.exp(-(deltaE/kappa)**2.)/step[2]
  258.         elif option == 2:
  259.             gD = 1./(1.+(deltaD/kappa)**2.)/step[0]
  260.             gS = 1./(1.+(deltaS/kappa)**2.)/step[1]
  261.             gE = 1./(1.+(deltaE/kappa)**2.)/step[2]
  262.  
  263.         # update matrices
  264.         D = gD*deltaD
  265.         E = gE*deltaE
  266.         S = gS*deltaS
  267.  
  268.         # subtract a copy that has been shifted 'Up/North/West' by one
  269.         # pixel. don't as questions. just do it. trust me.
  270.         UD[:] = D
  271.         NS[:] = S
  272.         EW[:] = E
  273.         UD[1:,: ,: ] -= D[:-1,:  ,:  ]
  274.         NS[: ,1:,: ] -= S[:  ,:-1,:  ]
  275.         EW[: ,: ,1:] -= E[:  ,:  ,:-1]
  276.  
  277.         # update the image
  278.         stackout += gamma*(UD+NS+EW)
  279.  
  280.         if ploton:
  281.             iterstring = "Iteration %i" %(ii+1)
  282.             ih.set_data(stackout[showplane,...].squeeze())
  283.             ax2.set_title(iterstring)
  284.             fig.canvas.draw()
  285.             # sleep(0.01)
  286.  
  287.     return stackout
Add Comment
Please, Sign In to add comment