phase.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. from PIL import Image, ImageEnhance
  2. import numpy as np
  3. def randomise (img, noise='uniform', noise_prop=1, contrast_adj=1):
  4. """Randomise the phase of an image.
  5. Keyword arguments:
  6. img -- a PIL image
  7. noise -- the type of distribution to draw the noise from. Can be one of:
  8. 'uniform': uniform distribution, between -pi and pi
  9. 'permute': randomly shuffle the image's existing phase
  10. 'normal': normal distribution, with mean of 0, and sd of 1
  11. noise_prop -- a float from 0 to 1 specifying how much of the image should be noise (e.g. 0.3 will produce an image with phase of 30% noise, 70% original)
  12. contrast_adj -- a float specifying a proportion of contrast adjustment. The contrast of `img` will be adjusted to this value before the fft is run, and the phase-altered output will then be reverted to the original image's contrast. Contrast artefacts can often be removed from phase-altered images by reducing this value from 1.
  13. """
  14. # adjust contrast
  15. if contrast_adj!=1:
  16. img_ie = ImageEnhance.Contrast(img)
  17. img = img_ie.enhance(contrast_adj)
  18. # fast fourier transform of the image as-is
  19. img_fft = np.fft.fftn(img)
  20. # get amplitude as distance from origin in complex plane
  21. amp = np.abs(img_fft)
  22. # get original image's phase
  23. ph = np.angle(img_fft)
  24. # get randomised phas
  25. if noise == 'uniform':
  26. ph_noise = np.random.uniform(-np.pi, np.pi, img_fft.shape)
  27. elif noise == 'permute':
  28. ph_noise = np.random.permutation(ph)
  29. elif noise == 'normal':
  30. ph_noise = np.random.normal(0, 1, img_fft.shape)
  31. # get new phase
  32. ph_new = ph * (1-noise_prop) + ph_noise * noise_prop
  33. # inverse fourier transform using the new phases
  34. # (absolute result is rounded to nearest integer)
  35. img_ph_rand = np.round(np.abs( np.fft.ifftn(amp * np.exp(1j * ph_new)) ))
  36. # convert to PIL image
  37. img_out = Image.fromarray(np.uint8(img_ph_rand))
  38. # revert contrast to original value
  39. if contrast_adj!=1:
  40. img_out_ie = ImageEnhance.Contrast(img_out)
  41. img_out = img_out_ie.enhance(1/contrast_adj)
  42. return(img_out)