00001 ## @package OrientationEstimation 00002 # This is a package which estimates gradient orientations with the linear structure tensor. 00003 # 00004 # Below, pieces of the actual code are shown in sequence, with a brief description of what 00005 # the code does preceding the corresponding code snippet. 00006 # 00007 # First, we give the proper usage for this module. 00008 # \par 00009 # @code 00010 # usage="\nOrientationEstimation.py target=theta.rsf datafile=data.rsf" 00011 # @endcode 00012 # 00013 # Then we import the SLIMpy, Numpy, rsf and slimproj packages into current module. 00014 # @code 00015 # from SLIMpy import * 00016 # import numpy as np 00017 # import rsf as sf 00018 # from slimproj import * 00019 # @endcode 00020 # 00021 # Set the default value for the input filename containing the initial gradient estimate of the image 00022 # @code 00023 # defaults = { 00024 # 'inputgrad_filename':'marmousi_grad.rsf', #Input data as y 00025 # } 00026 # @endcode 00027 # 00028 # The new_average_bldr function is a builder function 00029 # which takes the image to which we wish to apply 00030 # the sliding average window (z) as its first argument 00031 # and the size of the averaging window (filtersize) as 00032 # its second argument. 00033 # @code 00034 # def new_average_bldr( vectors ): 00035 # \""" 00036 # use our new averaging operator 00037 # \""" 00038 # z = vectors[0] 00039 # filtersize = vectors[1] 00040 # @endcode 00041 # Initialize averaging filters in x and y directions 00042 # (both are the same in this case) 00043 # @code 00044 # averagefilterx = np.ones((1,filtersize))/filtersize 00045 # averagefiltery = np.ones((1,filtersize))/filtersize 00046 # @endcode 00047 # 00048 # Allocate the output (averaged) image 00049 # @code 00050 # (M,N) = z.shape 00051 # x = np.zeros((M,N),'f') 00052 # @endcode 00053 # 00054 # First average along each row, and then along each column. 00055 # This is equivalent to taking the average in a rectangular 00056 # (in this case square) window across the image. 00057 # @code 00058 # for i in range(0,M): 00059 # x[i,:] = np.convolve(z[i,:],np.ones(filtersize)/filtersize,mode='same') 00060 # 00061 # for j in range(0,N): 00062 # x[:,j] = np.convolve(x[:,j],np.ones(filtersize)/filtersize,mode='same') 00063 # @endcode 00064 # 00065 # Return the image computed by taking windowed averages. 00066 # @code 00067 # return x 00068 # @endcode 00069 # 00070 # 00071 # Read in input image. 00072 # @code 00073 # def OrientationEstimation( target, source, env ): 00074 # inputfilename = source[0] 00075 # inputimage = sf.Input(source[0]) 00076 # @endcode 00077 # 00078 # M is the number of rows and N is the number of columns in image 00079 # @code 00080 # M = inputimage.int("n2") 00081 # N = inputimage.int("n1") 00082 # @endcode 00083 # 00084 # Read in previously computed partial derivative in x direction 00085 # @code 00086 # Jx = np.zeros((M,N),'f') 00087 # noisyinputgradx_filename = source[1] 00088 # noisyinputgradxrsf = sf.Input(noisyinputgradx_filename) 00089 # noisyinputgradxrsf.read(Jx) 00090 # @endcode 00091 # 00092 # Read in previously computed partial derivative in y direction 00093 # @code 00094 # Jy = np.zeros((M,N),'f') 00095 # noisyinputgrady_filename = source[2] 00096 # noisyinputgradyrsf = sf.Input(noisyinputgrady_filename) 00097 # noisyinputgradyrsf.read(Jy) 00098 # @endcode 00099 # 00100 # Allocate space for elements of structure tensor and initialize to zero. 00101 # @code 00102 # Jtensorxx = np.zeros((M,N)) 00103 # Jtensorxy = np.zeros((M,N)) 00104 # Jtensoryy = np.zeros((M,N)) 00105 # @endcode 00106 # 00107 # Form elements of structure tensor (Outer product of gradient vector with itself). 00108 # @code 00109 # Jtensorxx = Jx*Jx 00110 # Jtensorxy = Jx*Jy 00111 # Jtensoryy = Jy*Jy 00112 # @endcode 00113 # 00114 # Replace each pixel's structure tensor with a local average of the structure tensor around 00115 # the pixel. 00116 # @code 00117 # averagefilterwidth = 5 00118 # Jtensorxx = new_average_bldr([Jtensorxx,averagefilterwidth]) 00119 # Jtensorxy = new_average_bldr([Jtensorxy,averagefilterwidth]) 00120 # Jtensoryy = new_average_bldr([Jtensoryy,averagefilterwidth]) 00121 # @endcode 00122 # 00123 # Estimated gradient orientation is in the same direction 00124 # as the eigenvector corresponding to the largest eigenvalue 00125 # of the structure tensor. 00126 # @code 00127 # Jtensoreig = np.zeros((2,M,N),'f') 00128 # Jmag = np.zeros((M,N),'f') 00129 # tempJ = np.zeros((2,2),'f') 00130 # for i in range(0,M): 00131 # for j in range(0,N): 00132 # tempJ[0,0] = Jtensorxx[i,j] 00133 # tempJ[0,1] = Jtensorxy[i,j] 00134 # tempJ[1,0] = Jtensorxy[i,j] 00135 # tempJ[1,1] = Jtensoryy[i,j] 00136 # tempJeigs = np.linalg.eig(tempJ) 00137 # if (tempJeigs[0][0] > tempJeigs[0][1]): 00138 # Jtensoreig[0][i][j] = tempJeigs[1][0][0] 00139 # Jtensoreig[1][i][j] = tempJeigs[1][0][1] 00140 # else: 00141 # Jtensoreig[0][i][j] = tempJeigs[1][1][0] 00142 # Jtensoreig[1][i][j] = tempJeigs[1][1][1] 00143 # Jmag[i][j] = np.sqrt(tempJeigs[0][0]+tempJeigs[0][1]) 00144 # @endcode 00145 # 00146 # Compute the gradient angle from the elements of the gradient vector. 00147 # @code 00148 # theta = np.array((M,N),'f') 00149 # theta = np.arctan(Jtensoreig[1,:,:]/Jtensoreig[0,:,:])+np.pi/2 00150 # @endcode 00151 # 00152 # Write the estimated gradient orientation to the RSF File specified by target. 00153 # @code 00154 # output = sf.Output(target) 00155 # 00156 # output.put("n1",N) 00157 # output.put("n2",M) 00158 # output.write(theta) 00159 # @endcode 00160 # 00161 # End the current function. 00162 # @code 00163 # End() 00164 # @endcode 00165 # 00166 # Finally, export the OrientationEstimation function so that it can be used by other programs. 00167 # @code 00168 # __all__ = ['OrientationEstimation'] 00169 # from slimproj_core.builders.CreateBuilders import add_to_slim_env 00170 # add_to_slim_env("OrientationEstimation",OrientationEstimation) 00171 # @endcode 00172 # 00173 00174 #!/usr/bin/env python 00175 #""" 00176 #DESCRIPTION: 00177 # Calculate gradient orientation of input image with a method robust to noise 00178 # using the Linear Structure Tensor 00179 # 00180 #PARAMETERS: 00181 # datafile: The noisy input for which we desire to calculate the gradient directions 00182 # Jx: x-component of gradient of input image 00183 # Jy: y-component of gradient of input image 00184 # Jmag: Gradient magnitude image 00185 # confthetafile: Filename where confidence in orientation estimation is stored 00186 # 00187 #REQUIREMENTS: 00188 # - Madagascar 00189 # - SLIMpy 00190 # 00191 #Author: 00192 # Reza Shahidi 00193 # Seismic Laboratory for Imaging and Modeling (SLIM) 00194 # Department of Earth & Ocean Sciences (EOS) 00195 # University of British Columbia (UBC) 00196 # 00197 #You may use this code only under the conditions and terms of the 00198 #license contained in the file LICENSE provided with this source 00199 #code. If you do not agree to these terms you may not use this 00200 #software. 00201 #""" 00202 # 00203 00204 usage="\nOrientationEstimation.py target=theta.rsf datafile=data.rsf" 00205 00206 from SLIMpy import * 00207 import numpy as np 00208 import rsf as sf 00209 from slimproj import * 00210 00211 # Set default values 00212 defaults = { 00213 'inputgrad_filename':'marmousi_grad.rsf', #Input data as y 00214 } 00215 00216 def new_average_bldr( vectors ): 00217 """ 00218 use our new averaging operator 00219 """ 00220 z = vectors[0] 00221 filtersize = vectors[1] 00222 averagefilterx = np.ones((1,filtersize))/filtersize 00223 averagefiltery = np.ones((1,filtersize))/filtersize 00224 00225 (M,N) = z.shape 00226 x = np.zeros((M,N),'f') 00227 for i in range(0,M): 00228 x[i,:] = np.convolve(z[i,:],np.ones(filtersize)/filtersize,mode='same') 00229 00230 for j in range(0,N): 00231 x[:,j] = np.convolve(x[:,j],np.ones(filtersize)/filtersize,mode='same') 00232 00233 return x 00234 00235 def OrientationEstimation( target, source, env ): 00236 """ 00237 Takes the image specified by source, and writes the gradient direction angle 00238 for the source image (lying between -pi and pi) to the RSF file specified by target. 00239 """ 00240 00241 # Read in file for which we want to compute the gradient direction 00242 inputfilename = source[0] 00243 inputimage = sf.Input(source[0]) 00244 00245 # Number of rows and columns in image 00246 M = inputimage.int("n2") 00247 N = inputimage.int("n1") 00248 00249 # Read in previously computed partial derivatives of input with noise added 00250 # Partial derivative in x direction 00251 noisyinputgradx_filename = source[1] 00252 noisyinputgradxrsf = sf.Input(noisyinputgradx_filename) 00253 Jx = np.zeros((M,N),'f') 00254 noisyinputgradxrsf.read(Jx) 00255 00256 # Partial derivative in y direction 00257 noisyinputgrady_filename = source[2] 00258 noisyinputgradyrsf = sf.Input(noisyinputgrady_filename) 00259 Jy = np.zeros((M,N),'f') 00260 noisyinputgradyrsf.read(Jy) 00261 00262 Jtensorxx = np.zeros((M,N)) 00263 Jtensorxy = np.zeros((M,N)) 00264 Jtensoryy = np.zeros((M,N)) 00265 00266 # Form structure tensor elements 00267 Jtensorxx = Jx*Jx 00268 Jtensorxy = Jx*Jy 00269 Jtensoryy = Jy*Jy 00270 00271 # Apply 5x5 averaging window on each of the computed structure tensor elements 00272 averagefilterwidth = 5 00273 Jtensorxx = new_average_bldr([Jtensorxx,averagefilterwidth]) 00274 Jtensorxy = new_average_bldr([Jtensorxy,averagefilterwidth]) 00275 Jtensoryy = new_average_bldr([Jtensoryy,averagefilterwidth]) 00276 00277 # Estimated gradient orientation is in the same direction 00278 # as the eigenvector corresponding to the largest eigenvalue 00279 # of the structure tensor 00280 Jtensoreig = np.zeros((2,M,N),'f') 00281 Jmag = np.zeros((M,N),'f') 00282 tempJ = np.zeros((2,2),'f') 00283 for i in range(0,M): 00284 for j in range(0,N): 00285 00286 # Form 2x2 Structure Tensor for Current Pixel 00287 tempJ[0,0] = Jtensorxx[i,j] 00288 tempJ[0,1] = Jtensorxy[i,j] 00289 tempJ[1,0] = Jtensorxy[i,j] 00290 tempJ[1,1] = Jtensoryy[i,j] 00291 00292 # Find Eigenvalues of Structure Tensor 00293 tempJeigs = np.linalg.eig(tempJ) 00294 00295 # Choose Eigenvector of Structure Tensor Corresponding to Larger Eigenvalue 00296 if (tempJeigs[0][0] > tempJeigs[0][1]): 00297 Jtensoreig[0][i][j] = tempJeigs[1][0][0] 00298 Jtensoreig[1][i][j] = tempJeigs[1][0][1] 00299 else: 00300 Jtensoreig[0][i][j] = tempJeigs[1][1][0] 00301 Jtensoreig[1][i][j] = tempJeigs[1][1][1] 00302 00303 # Estimated Gradient Magnitude 00304 Jmag[i][j] = np.sqrt(tempJeigs[0][0]+tempJeigs[0][1]) 00305 00306 theta = np.array((M,N),'f') 00307 00308 # Theta is the estimated gradient orientation 00309 theta = np.arctan(Jtensoreig[1,:,:]/Jtensoreig[0,:,:]) 00310 00311 # Write out theta to file 00312 output = sf.Output(target) 00313 00314 # Write the original multiples to RSF File 00315 output.put("n1",N) 00316 output.put("n2",M) 00317 output.write(theta) 00318 00319 End() 00320 00321 __all__ = ['OrientationEstimation'] 00322 from slimproj_core.builders.CreateBuilders import add_to_slim_env 00323 add_to_slim_env("OrientationEstimation",OrientationEstimation)