ali_m

fastaniso

Sep 3rd, 2012 (edited)
13,891
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 [email protected]
  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.  
  75.     June 2000  original version.      
  76.     March 2002 corrected diffusion eqn No 2.
  77.     July 2012 translated to Python
  78.     """
  79.  
  80.     # ...you could always diffuse each color channel independently if you
  81.     # really want
  82.     if img.ndim == 3:
  83.         warnings.warn("Only grayscale images allowed, converting to 2D matrix")
  84.         img = img.mean(2)
  85.  
  86.     # initialize output array
  87.     img = img.astype('float32')
  88.     imgout = img.copy()
  89.  
  90.     # initialize some internal variables
  91.     deltaS = np.zeros_like(imgout)
  92.     deltaE = deltaS.copy()
  93.     NS = deltaS.copy()
  94.     EW = deltaS.copy()
  95.     gS = np.ones_like(imgout)
  96.     gE = gS.copy()
  97.  
  98.     # create the plot figure, if requested
  99.     if ploton:
  100.         import pylab as pl
  101.         from time import sleep
  102.  
  103.         fig = pl.figure(figsize=(20,5.5),num="Anisotropic diffusion")
  104.         ax1,ax2 = fig.add_subplot(1,2,1),fig.add_subplot(1,2,2)
  105.  
  106.         ax1.imshow(img,interpolation='nearest')
  107.         ih = ax2.imshow(imgout,interpolation='nearest',animated=True)
  108.         ax1.set_title("Original image")
  109.         ax2.set_title("Iteration 0")
  110.  
  111.         fig.canvas.draw()
  112.  
  113.     for ii in xrange(niter):
  114.  
  115.         # calculate the diffs
  116.         deltaS[:-1,: ] = np.diff(imgout,axis=0)
  117.         deltaE[: ,:-1] = np.diff(imgout,axis=1)
  118.  
  119.         # conduction gradients (only need to compute one per dim!)
  120.         if option == 1:
  121.             gS = np.exp(-(deltaS/kappa)**2.)/step[0]
  122.             gE = np.exp(-(deltaE/kappa)**2.)/step[1]
  123.         elif option == 2:
  124.             gS = 1./(1.+(deltaS/kappa)**2.)/step[0]
  125.             gE = 1./(1.+(deltaE/kappa)**2.)/step[1]
  126.  
  127.         # update matrices
  128.         E = gE*deltaE
  129.         S = gS*deltaS
  130.  
  131.         # subtract a copy that has been shifted 'North/West' by one
  132.         # pixel. don't as questions. just do it. trust me.
  133.         NS[:] = S
  134.         EW[:] = E
  135.         NS[1:,:] -= S[:-1,:]
  136.         EW[:,1:] -= E[:,:-1]
  137.  
  138.         # update the image
  139.         imgout += gamma*(NS+EW)
  140.  
  141.         if ploton:
  142.             iterstring = "Iteration %i" %(ii+1)
  143.             ih.set_data(imgout)
  144.             ax2.set_title(iterstring)
  145.             fig.canvas.draw()
  146.             # sleep(0.01)
  147.  
  148.     return imgout
  149.  
  150. def anisodiff3(stack,niter=1,kappa=50,gamma=0.1,step=(1.,1.,1.),option=1,ploton=False):
  151.     """
  152.     3D Anisotropic diffusion.
  153.  
  154.     Usage:
  155.     stackout = anisodiff(stack, niter, kappa, gamma, option)
  156.  
  157.     Arguments:
  158.             stack  - input stack
  159.             niter  - number of iterations
  160.             kappa  - conduction coefficient 20-100 ?
  161.             gamma  - max value of .25 for stability
  162.             step   - tuple, the distance between adjacent pixels in (z,y,x)
  163.             option - 1 Perona Malik diffusion equation No 1
  164.                      2 Perona Malik diffusion equation No 2
  165.             ploton - if True, the middle z-plane will be plotted on every
  166.                  iteration
  167.  
  168.     Returns:
  169.             stackout   - diffused stack.
  170.  
  171.     kappa controls conduction as a function of gradient.  If kappa is low
  172.     small intensity gradients are able to block conduction and hence diffusion
  173.     across step edges.  A large value reduces the influence of intensity
  174.     gradients on conduction.
  175.  
  176.     gamma controls speed of diffusion (you usually want it at a maximum of
  177.     0.25)
  178.  
  179.     step is used to scale the gradients in case the spacing between adjacent
  180.     pixels differs in the x,y and/or z axes
  181.  
  182.     Diffusion equation 1 favours high contrast edges over low contrast ones.
  183.     Diffusion equation 2 favours wide regions over smaller ones.
  184.  
  185.     Reference:
  186.     P. Perona and J. Malik.
  187.     Scale-space and edge detection using ansotropic diffusion.
  188.     IEEE Transactions on Pattern Analysis and Machine Intelligence,
  189.     12(7):629-639, July 1990.
  190.  
  191.     Original MATLAB code by Peter Kovesi  
  192.     School of Computer Science & Software Engineering
  193.     The University of Western Australia
  194.     pk @ csse uwa edu au
  195.     <http://www.csse.uwa.edu.au>
  196.  
  197.     Translated to Python and optimised by Alistair Muldal
  198.     Department of Pharmacology
  199.     University of Oxford
  200.  
  201.     June 2000  original version.      
  202.     March 2002 corrected diffusion eqn No 2.
  203.     July 2012 translated to Python
  204.     """
  205.  
  206.     # ...you could always diffuse each color channel independently if you
  207.     # really want
  208.     if stack.ndim == 4:
  209.         warnings.warn("Only grayscale stacks allowed, converting to 3D matrix")
  210.         stack = stack.mean(3)
  211.  
  212.     # initialize output array
  213.     stack = stack.astype('float32')
  214.     stackout = stack.copy()
  215.  
  216.     # initialize some internal variables
  217.     deltaS = np.zeros_like(stackout)
  218.     deltaE = deltaS.copy()
  219.     deltaD = deltaS.copy()
  220.     NS = deltaS.copy()
  221.     EW = deltaS.copy()
  222.     UD = deltaS.copy()
  223.     gS = np.ones_like(stackout)
  224.     gE = gS.copy()
  225.     gD = gS.copy()
  226.  
  227.     # create the plot figure, if requested
  228.     if ploton:
  229.         import pylab as pl
  230.         from time import sleep
  231.  
  232.         showplane = stack.shape[0]//2
  233.  
  234.         fig = pl.figure(figsize=(20,5.5),num="Anisotropic diffusion")
  235.         ax1,ax2 = fig.add_subplot(1,2,1),fig.add_subplot(1,2,2)
  236.  
  237.         ax1.imshow(stack[showplane,...].squeeze(),interpolation='nearest')
  238.         ih = ax2.imshow(stackout[showplane,...].squeeze(),interpolation='nearest',animated=True)
  239.         ax1.set_title("Original stack (Z = %i)" %showplane)
  240.         ax2.set_title("Iteration 0")
  241.  
  242.         fig.canvas.draw()
  243.  
  244.     for ii in xrange(niter):
  245.  
  246.         # calculate the diffs
  247.         deltaD[:-1,: ,:  ] = np.diff(stackout,axis=0)
  248.         deltaS[:  ,:-1,: ] = np.diff(stackout,axis=1)
  249.         deltaE[:  ,: ,:-1] = np.diff(stackout,axis=2)
  250.  
  251.         # conduction gradients (only need to compute one per dim!)
  252.         if option == 1:
  253.             gD = np.exp(-(deltaD/kappa)**2.)/step[0]
  254.             gS = np.exp(-(deltaS/kappa)**2.)/step[1]
  255.             gE = np.exp(-(deltaE/kappa)**2.)/step[2]
  256.         elif option == 2:
  257.             gD = 1./(1.+(deltaD/kappa)**2.)/step[0]
  258.             gS = 1./(1.+(deltaS/kappa)**2.)/step[1]
  259.             gE = 1./(1.+(deltaE/kappa)**2.)/step[2]
  260.  
  261.         # update matrices
  262.         D = gD*deltaD
  263.         E = gE*deltaE
  264.         S = gS*deltaS
  265.  
  266.         # subtract a copy that has been shifted 'Up/North/West' by one
  267.         # pixel. don't as questions. just do it. trust me.
  268.         UD[:] = D
  269.         NS[:] = S
  270.         EW[:] = E
  271.         UD[1:,: ,: ] -= D[:-1,:  ,:  ]
  272.         NS[: ,1:,: ] -= S[:  ,:-1,:  ]
  273.         EW[: ,: ,1:] -= E[:  ,:  ,:-1]
  274.  
  275.         # update the image
  276.         stackout += gamma*(UD+NS+EW)
  277.  
  278.         if ploton:
  279.             iterstring = "Iteration %i" %(ii+1)
  280.             ih.set_data(stackout[showplane,...].squeeze())
  281.             ax2.set_title(iterstring)
  282.             fig.canvas.draw()
  283.             # sleep(0.01)
  284.  
  285.     return stackout
Add Comment
Please, Sign In to add comment