|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +""" |
| 4 | +Implementation of Phase Stretch Transform (PST) in Python |
| 5 | +@author: Madhuri Suthar, Ph.D. candidate, Jalali Lab, Department of Electrical and Computer Engineering, UCLA |
| 6 | +
|
| 7 | +PST or Phase Stretch Transform is a physics-inspired edge detection algorithm that detects intensity variations in an image [1,2]. |
| 8 | +PST operates on an input greyscale image and outputs an edge map. The output egde map, same as the size of the input image, is binary with |
| 9 | +pixel value equal to 1 where the PST operator finds sharp transitions in intensity and 0 elsewhere. The PST operator can also return |
| 10 | +a continous level edge map (i.e. without thresholding and morphological operations) |
| 11 | +
|
| 12 | +The PST operator cascades Gaussian smoothing, application of a nonlinear frequency-dependent phase kernel in frequency domain and a phase detection in spatial domain. |
| 13 | +To implement the first step, an isotropic gaussian filter with a user defined scale (LPF) is designed and operated on the image. |
| 14 | +Next, a 2D PST phase kernel is designed in frequency domain and applied to the spectrum of the input image. The output of the transform is the |
| 15 | +phase in the spatial domain. The amount of phase applied to the image is frequency dependent with higher amount of phase applied to higher frequency features of the |
| 16 | +image. Since sharp transitions, such as edges and corners, contain higher frequencies, PST emphasizes the edge information. Features can |
| 17 | +be further enhanced by applying thresholding and morphological operations. |
| 18 | +For more information please visit: https://en.wikipedia.org/wiki/Phase_stretch_transform |
| 19 | +
|
| 20 | +[out PST_Kernel]= PST(Image,LPF,Phase_strength,Warp_strength, Threshold_min, Threshold_max, Morph_flag) takes the image I and applies |
| 21 | +PST phase kernel parameters are described as follows: |
| 22 | +
|
| 23 | +Parameters |
| 24 | +---------- |
| 25 | +LPF : Isotropic Gaussian localization filter Full Width at Half Maximum (FWHM) (min : 0, max : 1) |
| 26 | +Phase_strength : PST Kernel Phase Strength (min : 0, max : 1) |
| 27 | +Warp_strength : PST Kernel Warp Strength (min : 0, max : 1) |
| 28 | +Threshold_min : minimum threshold (min : -1, max : 0) |
| 29 | +Threshold_max : maximum threshold (min : 0, max : 1) |
| 30 | +Morph_flag allows user to compute the analog edge (if Morph_flag=0) or the digital edge (analog edge followed |
| 31 | +by thresholding and morphological operations, if Morph_flag=1). |
| 32 | +
|
| 33 | +Copyright |
| 34 | +--------- |
| 35 | +PST function is developed in Jalali Lab at University of California, |
| 36 | +Los Angeles (UCLA). PST is a spin-off from research on the photonic time stretch technique in Jalali lab at UCLA. |
| 37 | +More information about the technique can be found in our group |
| 38 | +website: http://www.photonics.ucla.edu |
| 39 | +This function is provided for research purposes only. A license must be |
| 40 | +obtained from the University of California, Los Angeles for any commercial |
| 41 | +applications. The software is protected under a US patent. |
| 42 | + |
| 43 | +Citations |
| 44 | +--------- |
| 45 | +1. M. H. Asghari, and B. Jalali, "Edge detection in digital images using dispersive phase stretch," International Journal of Biomedical Imaging, Vol. 2015, Article ID 687819, pp. 1-6 (2015). |
| 46 | +2. M. H. Asghari, and B. Jalali, "Physics-inspired image edge detection," IEEE Global Signal and Information Processing Symposium (GlobalSIP 2014), paper: WdBD-L.1, Atlanta, December 2014. |
| 47 | +3. M. Suthar, H. Asghari, and B. Jalali, "Feature Enhancement in Visually Impaired Images", IEEE Access 6 (2018): 1407-1415. |
| 48 | +4. Y. Han, and B. Jalali, "Photonic time-stretched analog-to-digital converter: Fundamental concepts and practical considerations", Journal of Lightwave Technology 21, no. 12 (2003): 3085. |
| 49 | +""" |
| 50 | +# Imports |
| 51 | +# [] Need to install mahotas library for morphological operations |
| 52 | +import math |
| 53 | +import numpy as np |
| 54 | +import mahotas as mh |
| 55 | + |
| 56 | +# Define functions |
| 57 | +def cart2pol(x, y): |
| 58 | + theta = np.arctan2(y, x) |
| 59 | + rho = np.hypot(x, y) |
| 60 | + return (theta, rho) |
| 61 | +def PST(I,LPF,Phase_strength,Warp_strength, Threshold_min, Threshold_max, Morph_flag): |
| 62 | + L=0.5 |
| 63 | + x = np.linspace(-L, L, I.shape[0]) |
| 64 | + y = np.linspace(-L, L, I.shape[1]) |
| 65 | + [X1, Y1] =(np.meshgrid(x, y)) |
| 66 | + X=X1.T |
| 67 | + Y=Y1.T |
| 68 | + [THETA,RHO] = cart2pol(X,Y) |
| 69 | + |
| 70 | + # Apply localization kernel to the original image to reduce noise |
| 71 | + Image_orig_f=((np.fft.fft2(I))) |
| 72 | + expo = np.fft.fftshift(np.exp(-np.power((np.divide(RHO, math.sqrt((LPF**2)/np.log(2)))),2))) |
| 73 | + Image_orig_filtered=np.real(np.fft.ifft2((np.multiply(Image_orig_f,expo)))) |
| 74 | + # Constructing the PST Kernel |
| 75 | + PST_Kernel_1=np.multiply(np.dot(RHO,Warp_strength), np.arctan(np.dot(RHO,Warp_strength)))-0.5*np.log(1+np.power(np.dot(RHO,Warp_strength),2)) |
| 76 | + PST_Kernel=PST_Kernel_1/np.max(PST_Kernel_1)*Phase_strength |
| 77 | + # Apply the PST Kernel |
| 78 | + temp=np.multiply(np.fft.fftshift(np.exp(-1j*PST_Kernel)),np.fft.fft2(Image_orig_filtered)) |
| 79 | + Image_orig_filtered_PST=np.fft.ifft2(temp) |
| 80 | + |
| 81 | + # Calculate phase of the transformed image |
| 82 | + PHI_features=np.angle(Image_orig_filtered_PST) |
| 83 | + |
| 84 | + if Morph_flag ==0: |
| 85 | + out=PHI_features |
| 86 | + else: |
| 87 | + # find image sharp transitions by thresholding the phase |
| 88 | + features = np.zeros((PHI_features.shape[0],PHI_features.shape[1])) |
| 89 | + features[PHI_features> Threshold_max] = 1 # Bi-threshold decision |
| 90 | + features[PHI_features< Threshold_min] = 1 # as the output phase has both positive and negative values |
| 91 | + features[I<(np.amax(I)/20)]=0 # Removing edges in the very dark areas of the image (noise) |
| 92 | + |
| 93 | + # apply binary morphological operations to clean the transformed image |
| 94 | + out = features |
| 95 | + out = mh.thin(out, 1) |
| 96 | + out = mh.bwperim(out, 4) |
| 97 | + out = mh.thin(out, 1) |
| 98 | + out = mh.erode(out, np.ones((1, 1))); |
| 99 | + |
| 100 | + return (out, PST_Kernel) |
0 commit comments