def delta(S, element=3): # inputs: # S : n x m x 3 or 4) Stokes # element : # as int or float: side length of square window (element x element) for averaging # as array or list: 2-D array describing (weighted) averaging window # eg. 0 1 0 # 1 1 1 # 0 1 0 # outputs: # n x m delta metric for array element_error = 'element must be an int or a 2D array' if type(element) in [int, float]: neighborhood = np.ones((element, element)) elif not type( element ) is np.ndarray: # if it is not an int or float it must be array raise ValueError(element_error) elif not len(element.shape) == 2: # if it's an array must be 2D raise ValueError(element_error) else: neighborhood = element # gives the number of cells that will be averaged for each cell. besides the edges, this will be element**2 N = conv(np.ones((S.shape[0], S.shape[1])), neighborhood, 'same') P = StD(S) #DoP ca = S[:, :, 1] / P # cos 2 AoLP sa = S[:, :, 2] / P # sin 2 AoLP cam = conv(ca, neighborhood, 'same') / N # averaged cosine sam = conv(sa, neighborhood, 'same') / N # averaged sine return np.sqrt(1 - (cam**2 + sam**2)) # delta metric, see Tyo et al 2016
def sobelFilter(image): ''' Description: This function will execute a Sobel Filter on the given image to find its horizontal and vertical gradients. The default filter is set to 3x3. Input: -image (np.array) Output: - grad_x (np.array) - grad_y (np.array) ''' # creating sobel kernels fx = np.array([1, 2, 1, 0, 0, 0, -1,-2,-1]) fy = np.array([-1,0,1, -2,0,2, -1,0,1]) fx = fx.reshape(3,3) fy = fy.reshape(3,3) grad_x = conv(image,fx) grad_y = conv(image,fy) return grad_x,grad_y
def yx_derivatives(im, sigma=4): # Create the gauss kernel for blurring the input image # It will be convolved with the image # wsize should be an odd number wsize = 5 gausskernel = gaussFilter(sigma, window = wsize) # fx is the filter for vertical gradient # fy is the filter for horizontal gradient # Please not the vertical direction is positive X fx = createFilter([0, 1, 0, 0, 0, 0, 0, -1, 0]) fy = createFilter([ 0, 0, 0, -1, 0, 1, 0, 0, 0]) imblurred = conv(im, gausskernel, 'same') # print "imout:", imout.shape gradx = conv(imblurred, fx, 'same') grady = conv(imblurred, fy, 'same') # Create the output array # (3d array of y, x, (y,x pair of immediate derivative)) points_shape = im.shape points_shape = (points_shape[0], points_shape[1], 2) points = np.empty(points_shape) points[:,:,0] = grady points[:,:,1] = gradx return points
def delta_aop(aop, element=3): # inputs: # aop: n x m array of angle of polarization in radians with a range of pi # element : # as int or float: side length of square window (element x element) for averaging # as array or list: 2-D array describing (weighted) averaging window # eg. 0 1 0 # 1 1 1 # 0 1 0 # outputs: # n x m delta metric for array # gives the number of cells that will be averaged for each cell. besides the edges, this will be element* if type(element) in [int, float]: neighborhood = np.ones((element, element)) elif not type(element) in [np.ndarray, list]: neighborhood = np.ones((3, 3)) else: neighborhood = element N = conv(np.ones((aop.shape[0], aop.shape[1])), neighborhood, 'same') ca = np.cos(2 * aop) sa = np.sin(2 * aop) # sin AoLP cam = conv(ca, neighborhood, 'same') / N # averaged cosine sam = conv(sa, neighborhood, 'same') / N # averaged sine return np.sqrt(1 - (cam**2 + sam**2)) # delta metric, see Tyo et al 2016
def ModifiedRicianPlusConstant(x, c, a, sig, n_angles=360, return_derivs=False): assert np.isclose(x[1]-x[0], x[-1]-x[-2]) # check for uniform spacing assert x[1] - x[0] > 0. #x must be increasing if not return_derivs: mr = ModifiedRician(x, a, sig, n_angles=n_angles, return_derivs=False) else: (mr, dmrda, dmrds) = ModifiedRician(x, a, sig, n_angles=n_angles, return_derivs=True) space = x[1] - x[0] ss = ( space/2.35 ) # sigma of normal - cen = (x[0] + x[-1])/2. + c*c #indic = np.where(x - cen < 0.)[0] # indicator function f = space*np.exp( (- 0.5/ss**2)*(x-cen)**2 )/(2*np.pi*ss) # this integrates to unity with good sampling sf = np.sum(f) if sf > 1.e-4: f /= sf g = conv(mr, f, mode='same', method='fft') if not return_derivs: return(g) else: dmrda = conv(dmrda, f, mode='same', method='fft') dmrds = conv(dmrds, f, mode='same', method='fft') dfdcen = f*(x-cen)/ss**2 dmrdcen = conv(mr, dfdcen, mode='same', method='fft') return(mr, np.array([dmrdcen, dmrda, dmrds]))
def harriscorner(img, thresh=0.2, sigma=1, window=3): gaussion = gaussFilter(sigma, window) gradkernel = np.asarray([-1, 0, 1], dtype='float32') dx = conv1d(img, gradkernel, 1, 3) dy = np.transpose(conv1d(np.transpose(img), gradkernel, 1, 3)) dx2 = dx * dx dy2 = dy * dy dxy = dx * dy dx2 = conv(dx2, gaussion, mode='same') dy2 = conv(dy2, gaussion, mode='same') dxy = conv(dxy, gaussion, mode='same') hessian = np.zeros((img.shape[0], img.shape[1], 2, 2), dtype='float32') hessian[:, :, 0, 0] = dx2 hessian[:, :, 0, 1] = dxy hessian[:, :, 1, 0] = dxy hessian[:, :, 1, 1] = dy2 cornerness = np.linalg.det(hessian) - 0.04 * np.trace( hessian, axis1=hessian.ndim - 2, axis2=hessian.ndim - 1) # eaignvalue = np.linalg.eigvals(hessian) # mask = np.zeros((img.shape[0], img.shape[1])) + 255 min = cornerness.min() max = cornerness.max() cornerness = (cornerness - min) / (max - min) mask[cornerness <= thresh] = 0 return mask
def convolve(img, psf, type='default', extend=True, mode='same', extend_margin=100, **kargs): """ Compute the convolution of two 2D signals: img and psf type: define the convolution type """ if extend is int: extend_margin = extend if extend: img = img_extend(img, extend_margin) if type is 'fft': from scipy.signal import fftconvolve as conv I = conv(img, psf, mode) elif type is 'default': from scipy.signal import convolve as conv I = conv(img, psf, mode) elif type is 'accurate': from scipy.signal import convolve2d as convolve I = conv(img, psf, mode) elif type is 'fft2': I = np.fft.fftshift((np.fft.irfft2(np.fft.rfft2(img) * np.fft.rfft2(psf)))) if extend: I = I[extend_margin:-extend_margin, extend_margin:-extend_margin] return I
def x_in(self, vis): if self.style == 'reichert': return [(conv(np.abs(vis), filt, mode='valid'), conv(vis, filt, mode='valid')) for filt in self.filters] else: return np.array( [conv(vis, filt, mode='valid') for filt in self.filters])
def ConvFresnel2D(self, g, x, diam_out, z, index_of_refraction=1, set_dx=True, return_derivs=False): if g.shape[0] != x.shape[0]: raise Exception("ConvFresnel2D: input field and grid must have same sampling.") if g.ndim != 2: raise Exception("ConvFresnel2D: input field array must be 2D.") if g.shape[0] != g.shape[1]: raise Exception("ConvFresnel2D: input field array must be square.") lam = self.params['wavelength']/index_of_refraction dx, diam = self.GetDxAndDiam(x) dx_new = dx # this will probably change dPhiTol_deg = self.params['max_chirp_step_deg'] dx_chirp = (dPhiTol_deg/180)*lam*z/(diam + diam_out) # sampling criterion for chirp (factors of pi cancel) if isinstance(set_dx, bool): # this step is needed so that 1 and 1.0 are not treated as True if set_dx == False: pass else: # use chirp sampling criterion if dx < dx_chirp: dx_new = dx_chirp else: # take dx_new to be value of set_dx if not isinstance(set_dx, float): raise Exception("ConvFresnel2D: set_dx must be a bool or a float.") if set_dx <= 0: raise Exception("ConvFresnel2D: numerical value of set_dx must be > 0.") dx_new = set_dx if not np.isclose(dx, dx_new): # interpolate g onto a grid with spacing of approx dx_new [g, x] = self.ResampleField2D(g, x, dx_new, kind=self.params['interp_style']) dx = x[1] - x[0] # make the kernel grid (s) match x as closely as possible ns = int(np.round(diam + diam_out)/dx) # number of points on extended kernel s = np.linspace(-diam/2 - diam_out/2 + dx/2, diam/2 + diam_out/2 - dx/2, ns) # spatial grid of extended kernel ind = np.where(np.abs(s) < diam_out/2)[0] # get the part of s within the 1D output grid [sx, sy] = np.meshgrid(s, s, indexing='xy') i_out = np.where(np.sqrt(sx*sx + sy*sy) > diam_out/2) #Calculate Fresnel convoltion kernel, (Goodman 4-16) # Note: the factor p = 1/(lam*z) is applied later # Also note: the factor -1j*np.exp(2j*np.pi*z/lam) causes unwanted oscillations with z kern = np.exp(1j*np.pi*(sx*sx + sy*sy)/(lam*z)) # Fresnel kernel if dx > dx_chirp: # Where does |s| exceed the max step for this dx? s_max = lam*z*self.params['max_chirp_step_deg']/(360*dx) null_ind = np.where(np.sqrt(sx*sx + sy*sy) > s_max) kern[null_ind[0], null_ind[1]] = 0 h = conv(kern, g, mode='same', method='fft') # h is on the s spatial grid h[i_out[0], i_out[1]] = 0. # zero the field outside the desired region h = h[ind[0]:ind[-1] + 1, ind[0]:ind[-1] + 1] p = 1/(lam*z) if not return_derivs: return([p*h, s[ind]]) #dpdz = (-1j/(lam*z*z) + 2*np.pi/(lam*lam*z))*np.exp(2j*np.pi*z/lam) # includes unwanted piston term dpdz = -1/(lam*z*z) dkerndz = -1j*np.pi*(sx*sx + sy*sy)*kern/(lam*z*z) dhdz = conv(dkerndz, g, mode='same', method='fft') dhdz[i_out[0], i_out[1]] = 0. dhdz = dhdz[ind[0]:ind[-1] + 1, ind[0]:ind[-1] + 1] return([p*h, dpdz*h + p*dhdz, s[ind]])
def cnnbp(self, y): n = len(self.layers) self.e = self.o - y self.L = 0.5 * np.sum(self.e**2) / self.e.shape[1] self.od = self.e * (self.o * (1 - self.o)) self.fvd = np.dot(self.ffW.transpose(), self.od) if self.layers[n - 1].types == 'c': self.fvd = self.fvd * (self.fv * (1 - self.fv)) sa = self.layers[n - 1].a[0].shape fvnum = sa[1] * sa[2] for j in range(len(self.layers[n - 1].a)): if self.layers[n - 1].d == None: self.layers[n - 1].d = {} self.layers[n - 1].d.setdefault(j) self.layers[n - 1].d[j] = self.fvd[(j * fvnum):( (j + 1) * fvnum), :].transpose().reshape(sa[0], sa[1], sa[2]) for l in range(n - 2, -1, -1): if self.layers[l].types == 'c': for j in range(len(self.layers[l].a)): if self.layers[l].d == None: self.layers[l].d = {} self.layers[l].d.setdefault(j) self.layers[l].d[j]=self.layers[l].a[j]*(1-self.layers[l].a[j])*\ np.kron(self.layers[l+1].d[j],np.ones(( self.layers[l+1].scale,self.layers[l+1].scale))/(self.layers[l+1].scale**2)) elif self.layers[l].types == 's': for j in range(len(self.layers[l].a)): if self.layers[l].d == None: self.layers[l].d = {} self.layers[l].d.setdefault(j) z = np.zeros(self.layers[l].a[0].shape) for i in range(len(self.layers[l + 1].a)): rotated = np.array( [rot90(self.layers[l + 1].k[j][i], 2)]) z = z + conv(self.layers[l + 1].d[i], rotated, 'full') self.layers[l].d[j] = z for l in range(1, n): m = self.layers[l].d[0].shape[0] if self.layers[l].types == 'c': for j in range(len(self.layers[l].a)): for i in range(len(self.layers[l - 1].a)): #self.layers[l].dk[i][j]=rot90(conv(self.layers[l-1].a[i],rot90(self.layers[l].d[j],2),'valid'),2) self.layers[l].dk[i][j] = self.layers[l].dk[i][j] * 0 for t in range(self.layers[l].d[0].shape[0]): self.layers[l].dk[i][j] += rot90( conv(self.layers[l - 1].a[i][t], rot90(self.layers[l].d[j][t], 2), 'valid'), 2) self.layers[l].dk[i][j] = self.layers[l].dk[i][j] / m self.layers[l].db[j] = np.sum(self.layers[l].d[j]) / m self.dffW = np.dot(self.od, self.fv.transpose()) / self.od.shape[1] self.dffb = np.mean(self.od, 1).reshape(self.ffb.shape)
def gaussianfilter(img, sigma): kernel = gauss(sigma)[0] kernel = (kernel / kernel.sum()) # Applying the gaussian kernel over rows and columns separatelly smooth_img = np.apply_along_axis(lambda x: conv(x, kernel, "same"), 0, img) smooth_img = np.apply_along_axis(lambda x: conv(x, kernel, "same"), 1, smooth_img) return smooth_img
def update_next(self): # alive pixels counts convoluted1 = conv(self.curr_board_array, self.__kernel, mode='same') mask1 = np.logical_and(np.logical_and(convoluted1>=2, convoluted1<=3), self.curr_board_array==1) # alive pixels do not count convoluted2 = conv(self.curr_board_array, self.__kernel, mode='same') mask2 = convoluted2==3 self.__next_board_array = (np.logical_or(mask1, mask2)*1).astype(np.uint8)
def cnnbp(self,y): n=len(self.layers) self.e=self.o-y self.L=0.5*np.sum(self.e**2)/self.e.shape[1] self.od=self.e*(self.o*(1-self.o)) self.fvd=np.dot(self.ffW.transpose(),self.od) if self.layers[n-1].types=='c': self.fvd=self.fvd*(self.fv*(1-self.fv)) sa=self.layers[n-1].a[0].shape fvnum=sa[1]*sa[2] for j in range(len(self.layers[n-1].a)): if self.layers[n-1].d==None: self.layers[n-1].d={} self.layers[n-1].d.setdefault(j) self.layers[n-1].d[j]=self.fvd[(j*fvnum):((j+1)*fvnum),:].transpose().reshape(sa[0],sa[1],sa[2]) for l in range(n-2,-1,-1): if self.layers[l].types=='c': for j in range(len(self.layers[l].a)): if self.layers[l].d==None: self.layers[l].d={} self.layers[l].d.setdefault(j) self.layers[l].d[j]=self.layers[l].a[j]*(1-self.layers[l].a[j])*\ np.kron(self.layers[l+1].d[j],np.ones(( self.layers[l+1].scale,self.layers[l+1].scale))/(self.layers[l+1].scale**2)) elif self.layers[l].types=='s': for j in range(len(self.layers[l].a)): if self.layers[l].d==None: self.layers[l].d={} self.layers[l].d.setdefault(j) z=np.zeros(self.layers[l].a[0].shape) for i in range(len(self.layers[l+1].a)): rotated=np.array([rot90(self.layers[l+1].k[j][i],2)]) z=z+conv(self.layers[l+1].d[i],rotated,'full') self.layers[l].d[j]=z for l in range(1,n): m=self.layers[l].d[0].shape[0] if self.layers[l].types=='c': for j in range(len(self.layers[l].a)): for i in range(len(self.layers[l-1].a)): #self.layers[l].dk[i][j]=rot90(conv(self.layers[l-1].a[i],rot90(self.layers[l].d[j],2),'valid'),2) self.layers[l].dk[i][j]=self.layers[l].dk[i][j]*0 for t in range(self.layers[l].d[0].shape[0]): self.layers[l].dk[i][j]+=rot90(conv(self.layers[l-1].a[i][t],rot90(self.layers[l].d[j][t],2),'valid'),2) self.layers[l].dk[i][j]=self.layers[l].dk[i][j]/m self.layers[l].db[j]=np.sum(self.layers[l].d[j])/m self.dffW=np.dot(self.od,self.fv.transpose())/self.od.shape[1] self.dffb = np.mean(self.od,1).reshape(self.ffb.shape);
def get_theta(mono_img): imin = mono_img.copy() * 255.0 wsize = 5 gausskernel = can.gaussFilter(4, window = wsize) fx = can.createFilter([0, 1, 0, 0, 0, 0, 0, -1, 0]) fy = can.createFilter([ 0, 0, 0, 1, 0, -1, 0, 0, 0]) imout = conv(imin, gausskernel, 'valid') gradxx = conv(imout, fx, 'valid') gradyy = conv(imout, fy, 'valid') gradx = np.zeros(mono_img.shape) grady = np.zeros(mono_img.shape) padx = (imin.shape[0] - gradxx.shape[0]) / 2.0 pady = (imin.shape[1] - gradxx.shape[1]) / 2.0 gradx[padx:-padx, pady:-pady] = gradxx grady[padx:-padx, pady:-pady] = gradyy # Net gradient is the square root of sum of square of the horizontal # and vertical gradients grad = hypot(gradx, grady) theta = arctan2(grady, gradx) theta = 180 + (180 / pi) * theta # Only significant magnitudes are considered. All others are removed xx, yy = where(grad < 5) theta[xx, yy] = 0 # The angles are quantized. This is the first step in non-maximum # supression. Since, any pixel will have only 4 approach directions. x0,y0 = where(((theta<22.5)+(theta>157.5)*(theta<202.5) +(theta>337.5)) == True) x45,y45 = where( ((theta>22.5)*(theta<67.5) +(theta>202.5)*(theta<247.5)) == True) x90,y90 = where( ((theta>67.5)*(theta<112.5) +(theta>247.5)*(theta<292.5)) == True) x135,y135 = where( ((theta>112.5)*(theta<157.5) +(theta>292.5)*(theta<337.5)) == True) theta = theta theta[x0,y0] = 0 theta[x45,y45] = 45 theta[x90,y90] = 90 theta[x135,y135] = 135 return theta
def ConvFresnel1D(self, g, x, diam_out, z, index_of_refraction=1, set_dx=True, return_derivs=False): if g.shape != x.shape: raise Exception("Input field and grid must have same dimensions.") lam = self.params['wavelength']/index_of_refraction dx, diam = self.GetDxAndDiam(x) dx_new = dx # this will probably change dPhiTol_deg = self.params['max_chirp_step_deg'] dx_chirp = (dPhiTol_deg/180)*lam*z/(diam + diam_out) # sampling criterion for chirp (factors of pi cancel) if isinstance(set_dx, bool): # this step is needed so that 1 and 1.0 are not treated as True if set_dx == False: pass else: # use chirp sampling criterion if dx_chirp < dx: dx_new = dx_chirp else: # take dx_new to be value of set_dx if not isinstance(set_dx, float): raise Exception("ConvFresnel1D: set_dx must be a bool or a float.") if set_dx <= 0: raise Exception("ConvFresnel1D: numerical value of set_dx must be > 0.") dx_new = set_dx if not np.isclose(dx, dx_new): # interpolate g onto a grid with spacing of (approx) dx_new [g, x] = self.ResampleField1D(g, x, dx_new) dx = x[1] - x[0] # make the kernel grid (s) match x as closely as possible ns = int(np.round(diam + diam_out)/dx) # number of points on extended kernel s = np.linspace(-diam/2 - diam_out/2 + dx/2, diam/2 + diam_out/2 - dx/2, ns) # spatial grid of extended kernel indices_out = np.where(np.abs(s) < diam_out/2)[0] # get the part of s within the output grid #Calculate Fresnel convoltion kernel, (Goodman 4-16) # Note: the factor p = 1/(lam*z) is applied later # Also note: the factor -1j*np.exp(2j*np.pi*z/lam) causes unwanted oscillations with z kern = np.exp(1j*np.pi*s*s/(lam*z)) # Fresnel kernel if dx > dx_chirp: # Where does |s| exceed the max step for this dx? s_max = lam*z*self.params['max_chirp_step_deg']/(360*dx) null_ind = np.where(np.abs(s) > s_max)[0] kern[null_ind] = 0 h = conv(kern, g, mode='same', method='fft') # h is on the s spatial grid p = 1/(lam*z) if not return_derivs: return([p*h[indices_out], s[indices_out]]) #dpdz = (-1j/(lam*z*z) + 2*np.pi/(lam*lam*z))*np.exp(2j*np.pi*z/lam) # includes unwanted oscillations dpdz = -1/(lam*z*z) dkerndz = -1j*np.pi*s*s*kern/(lam*z*z) dhdz = conv(dkerndz, g, mode='same', method='fft') s = s[indices_out] h = h[indices_out] dhdz = dhdz[indices_out] return([p*h, dpdz*h + p*dhdz, s])
def _centripetal_autowave_update(self): '''Curvature flow model of W: 4) W{A} = A' = [[F_2a'{M{A'}} + F_1a'{A'}] < 0.5] 5) A' = A + [F_1a{M{A}} > 0.5] 6) [F_1a{X}]_ij = X_ij if A_ij == 0 else 0 7) [F_2a{X}]_ij = X_ij if A_ij == 1 else 0 8) [X > d]_ij = 1 if X_ij >= d else 0 9) [X < d]_ij = 1 if X_ij <= d else 0 ''' M_Y = conv(self.Y, self.W, mode='same') Y_p = self.Y + (np.where(self.Y==0, M_Y, 0) >= 0.5) M_Yp = conv(Y_p, self.W, mode='same') W = Y_p + ((np.where(Y_p==1, M_Yp, 0) + np.where(Y_p==0, Y_p, 0)) <= 0.5) return W
def cnnff(self, x): #print x self.layers[0].a = {} self.layers[0].a.setdefault(0) self.layers[0].a[0] = x.copy() inputmap = 1 n = len(self.layers) for l in range(1, n): if self.layers[l].types == 's': for j in range(inputmap): temp = np.ones( (self.layers[l].scale, self.layers[l].scale)) / (self.layers[l].scale**2) z = conv(self.layers[l - 1].a[j], np.array([temp]), 'valid') z = np.array( z)[:, ::self.layers[l].scale, ::self.layers[l].scale] if self.layers[l].a == None: self.layers[l].a = {} self.layers[l].a.setdefault(j) self.layers[l].a[j] = z if self.layers[l].types == 'c': if self.layers[l].a == None: self.layers[l].a = {} for j in range(self.layers[l].out): #for each outmaps z = np.zeros(self.layers[l - 1].a[0].shape - np.array([ 0, self.layers[l].kernelsize - 1, self.layers[l].kernelsize - 1 ])) for i in range(inputmap): #cumulate from inputmaps z += conv(self.layers[l - 1].a[i], np.array([self.layers[l].k[i][j]]), 'valid') self.layers[l].a.setdefault(j) self.layers[l].a[j] = sigmoid(z + self.layers[l].b[j]) inputmap = self.layers[l].out self.fv = None for j in range(len(self.layers[n - 1].a)): sa = self.layers[n - 1].a[j].shape p = self.layers[n - 1].a[j].reshape(sa[0], sa[1] * sa[2]).copy() if (self.fv == None): self.fv = p else: self.fv = np.concatenate((self.fv, p), axis=1) self.fv = self.fv.transpose() self.o = sigmoid(np.dot(self.ffW, self.fv) + self.ffb)
def circstd(aop, element=3): if type(element) in [int, float]: neighborhood = np.ones((element, element)) elif not type(element) in [np.ndarray, list]: neighborhood = np.ones((3, 3)) else: neighborhood = element N = conv(np.ones((aop.shape[0], aop.shape[1])), neighborhood, 'same') ca = np.cos(2 * aop) sa = np.sin(2 * aop) # sin AoLP cam = conv(ca, neighborhood, 'same') / N # averaged cosine sam = conv(sa, neighborhood, 'same') / N # averaged sine R = np.hypot(sam, cam) return np.sqrt(-2 * np.log(R)) / 2.0
def lucas_kanade(images, window_size=5, tau=1e-2): """ Inputs: images: list of 2 images at time t and t+1 window_size: patch size of (window_size x window_size) around each pixel tau: threshold for smallest eigen value to ensure "cornerness" or validity of flow Output: (u,v, valid) = a tuple of u and v components of the flow field at each point and whether the point is valid (0 or 1) """ img1 = images[0] img2 = images[1] kernel_x = np.array([[-1., 1.], [-1., 1.]]) kernel_y = np.array([[-1., -1.], [1., 1.]]) kernel_t = np.array([[1., 1.], [1., 1.]]) # *.25 # window_size is odd, all the pixels with offset in between [-w, w] are inside the window w = int(window_size / 2) # ------Implement Lucas Kanade-------- # for each point, calculate I_x, I_y, I_t mode = 'same' fx = conv(img1, kernel_x, boundary='symm', mode=mode) fy = conv(img1, kernel_y, boundary='symm', mode=mode) ft = conv(img2, kernel_t, boundary='symm', mode=mode) + \ conv(img1, -kernel_t, boundary='symm', mode=mode) u = np.zeros(img1.shape) v = np.zeros(img1.shape) valid = np.zeros(img1.shape) # within window window_size * window_size for i in range(w, img1.shape[0] - w): for j in range(w, img1.shape[1] - w): Ix = fx[i - w:i + w + 1, j - w:j + w + 1].flatten() Iy = fy[i - w:i + w + 1, j - w:j + w + 1].flatten() It = ft[i - w:i + w + 1, j - w:j + w + 1].flatten() b = np.reshape(It, (It.shape[0], 1)) # get b here A = np.vstack((Ix, Iy)).T # get A here # if the smallest eigenvalue of A'A is larger than the threshold τ: if np.min(abs(np.linalg.eigvals(np.matmul(A.T, A)))) >= tau: nu = np.matmul(np.linalg.pinv(A), b) # get velocity here u[i, j] = nu[0] v[i, j] = nu[1] valid[i, j] = 1 return (u, v, valid)
def voigt(x,c1,w1,c2,w2): """ Voigt function: convolution of Lorentzian and Gaussian. Convolution implemented with the FFT convolve function in scipy. NOT NORMALISED """ ### Create larger array so convolution doesn't screw up at the edges of the arrays # this assumes nicely behaved x-array... # i.e. x[0] == x.min() and x[-1] == x.max(), monotonically increasing dx = (x[-1]-x[0])/len(x) xp_min = x[0] - len(x)/3 * dx xp_max = x[-1] + len(x)/3 * dx xp = linspace(xp_min,xp_max,3*len(x)) L = lorentzian(xp,c1,w1) G = gaussian(xp,c2,w2) #convolve V = conv(L,G,mode='same') #normalise to unity height !!! delete me later !!! V /= V.max() #create interpolation function to convert back to original array size fn_out = interp(xp,V) return fn_out(x)
def gaussFilter(image,sigma,window): ''' Description: This function will execute a Gaussian Blurring Filter on the given image. The sigma and window size are set to default sigma = 2 and window = 5x5. Input: -image (np.array) -sigma (int) -window size (int) Output: - blurred_im (np.array) ''' # creating an empty kernel kernel = np.zeros((window,window)) # centre of the kernel c0 = window // 2 # computing kernel using Gaussian function for x in range(window): for y in range(window): r = np.hypot((x-c0),(y-c0)) #calculating magnitude of the centre pixel. x^2 + y^2 val = (1.0/2*np.math.pi*sigma)*np.math.exp(-(r*r)/(2*sigma*sigma)) # computes gaussian filter kernel[x,y] = val kernel = kernel / kernel.sum() # executes convolution blurred_im = conv(np.asarray(image),kernel)[1:-1,1:-1] return blurred_im
def voigt(x, c1, w1, c2, w2): """ Voigt function: convolution of Lorentzian and Gaussian. Convolution implemented with the FFT convolve function in scipy. NOT NORMALISED """ ### Create larger array so convolution doesn't screw up at the edges of the arrays # this assumes nicely behaved x-array... # i.e. x[0] == x.min() and x[-1] == x.max(), monotonically increasing dx = (x[-1] - x[0]) / len(x) xp_min = x[0] - len(x) / 3 * dx xp_max = x[-1] + len(x) / 3 * dx xp = linspace(xp_min, xp_max, 3 * len(x)) L = lorentzian(xp, c1, w1) G = gaussian(xp, c2, w2) #convolve V = conv(L, G, mode='same') #normalise to unity height !!! delete me later !!! V /= V.max() #create interpolation function to convert back to original array size fn_out = interp(xp, V) return fn_out(x)
def windolf_sampling(self, params, layer): a = np.abs(params) alpha = np.angle(params) if layer=='visible': rates = np.abs(self.clamp) phases = vm(alpha, a*rates / self.sigma_sq) return rates*np.exp(1j*phases) else: bessels = bessel(a - self.biases)/ self.sigma_sq custom_kernel = np.ones((self.pool_size, self.pool_size)) sum_bessels = conv(bessels, custom_kernel, mode='valid') # Downsample sum_bessels = sum_bessels[0::self.pool_stride, 0::self.pool_stride] bessel_sftmx_denom = 1.0 + sum_bessels upsampled_denom = bessel_sftmx_denom.repeat(self.pool_stride, axis=0).repeat(self.pool_stride, axis=1) hid_cat_P = bessels / upsampled_denom pool_P = 1.0 - 1.0 / bessel_sftmx_denom hid_rates, pool_rates = self._dbn_maxpool_sample_helper(hid_cat_P, pool_P) hid_phases = vm(alpha, a*hid_rates / self.sigma_sq) hid_samples = hid_rates*np.exp(1j*hid_phases) pool_phases = np.sum(imx.view_as_blocks(hid_phases, (self.pool_size, self.pool_size)), axis=(2,3)) pool_samples = pool_rates*np.exp(1j*pool_phases) return hid_samples, pool_samples
def fft_submatrix_max(A): """ Searches for the rectangular subarray of A with maximum sum Uses FFT-based convolution operations """ M, N = A.shape this_location, max_value = ((0, 0), (0, 0)), 0 t0 = time.time() for m, n in itertools.product(xrange(2, M), xrange(2, N)): convolved = conv(A, np.ones((m, n)), mode='same') row, col = np.unravel_index(convolved.argmax(), convolved.shape) # index offsets for odd dimension length: if m % 2 == 1: m_off = 1 else: m_off = 0 if n % 2 == 1: n_off = 1 else: n_off = 0 this_location = ( slice(row - m / 2, row + m / 2 + m_off), slice(col - n / 2, col + n / 2 + n_off)) value = A[this_location].sum() if value >= max_value: max_value = value location = this_location location, max_value = local_search(A, location) t = time.time() - t0 return location, max_value, t
def gradientCalculator(im, sigma): ''' Helper function that calculates the array of gradient directions for an input image. This will be used in Part 5 to make the paint strokes orthogonal to edge directions. ''' imin = im.copy() * 255.0 # Create the gauss kernel for blurring the input image # It will be convolved with the image # wsize should be an odd number wsize = 5 gausskernel = gaussFilter(sigma, window = wsize) # fx is the filter for vertical gradient # fy is the filter for horizontal gradient # Please note the vertical direction is positive X fx = createFilter([0, 1, 0, 0, 0, 0, 0, -1, 0]) fy = createFilter([ 0, 0, 0, -1, 0, 1, 0, 0, 0]) imout = conv(imin, gausskernel, 'valid') # print "imout:", imout.shape gradxx = conv(imout, fx, 'valid') gradyy = conv(imout, fy, 'valid') gradx = np.zeros(im.shape) grady = np.zeros(im.shape) padx = (imin.shape[0] - gradxx.shape[0]) / 2.0 pady = (imin.shape[1] - gradxx.shape[1]) / 2.0 gradx[padx:-padx, pady:-pady] = gradxx grady[padx:-padx, pady:-pady] = gradyy # Net gradient is the square root of sum of square of the horizontal # and vertical gradients grad = hypot(gradx, grady) theta = arctan2(grady, gradx) # clear gradients below threshold 5 (for Part5) xx, yy = where(grad < 5) theta[xx, yy] = 0 grad[xx, yy] = 0 return theta
def matched_filter(self, matching_template, signal, method='lfilt'): """ Implementation of a matched filter, using either the FIR method using an lfilter, or by using correlation directly. matching_template - waveform to match to, must be smaller than signal [1-D numpy array] signal - signal under test, must be longer than matching_template [1-D numpy array] fs - sample rate of the signal [Hz, float] method: 'lfilt' - Uses scipys lfilter with the reversed template acting as the b coefficients. 'conv'- using scipys convolution function to convolve the reversed template with the signal. 'fftconv' - using scipys fftconv function function to convolve the reversed template with the signal. 'corr'- using scipys correlate function to directly correlate the template to the signal. """ if method is 'lfilt': matching_template = matching_template[::-1] # flip the template matched_signal = lfilt(matching_template, [1.0], signal) elif method is 'conv': matching_template = matching_template[::-1] # flip the template matched_signal = conv(signal, matching_template, mode='same', method='direct') elif method is 'fftconv': matching_template = matching_template[::-1] # flip the template matched_signal = conv(signal, matching_template, mode='same', method='fft') elif method is 'corr': matched_signal = corr(signal, matching_template, mode='same', method='auto') return matched_signal
def harris_corner_detector(im): """ Detects harris corners. Make sure the returned coordinates are x major!!! :param im: A 2D array representing an image. :return: An array with shape (N,2), where ret[i,:] are the [x,y] coordinates of the ith corner points. """ x_derivative = conv(im, X_DERIVATIVE_KERNEL, mode='same', boundary='symm') y_derivative = conv(im, Y_DERIVATIVE_KERNEL, mode='same', boundary='symm') Ix2 = blur_spatial(x_derivative**2, BLUR_KERNEL_SIZE) Iy2 = blur_spatial(y_derivative**2, BLUR_KERNEL_SIZE) IxIy = blur_spatial(x_derivative * y_derivative, BLUR_KERNEL_SIZE) m_det = (Ix2 * Iy2) - (IxIy * IxIy) m_trace = Ix2 + Iy2 response_values = m_det - RESPONSE_FACTOR * (m_trace**2) binary_response = non_maximum_suppression(response_values) corners_indices = np.argwhere(binary_response.T) return corners_indices
def create_kernel(kernel_size): counter = kernel_size kernel = np.array([1]).reshape(1, 1).astype('float64') while counter > 1: a = np.array([1, 1]).reshape(1, 2).astype('float64') kernel = (conv(kernel, a)) counter = counter - 1 return kernel / np.sum(kernel)
def validateBattlefield_03(field): """ """ from scipy.signal import convolve2d as conv b = [[[[1 for j in range(i)]], [[1] for j in range(i)]] for i in range(1, 5)] b += [[[[1, 0], [0, 1]], [[0, 1], [1, 0]]]] count = [1, 2, 3, 4, 2] c = [40, 10, 4, 1, 0] for i in range(5): c0 = conv(field, b[i][0]) c1 = conv(field, b[i][1]) if sum([list(j).count(count[i]) for j in c0]) + sum([list(j).count(count[i]) for j in c1]) != c[i]: return False return True
def retrieve_gaussian_components(img, sigma, spacing, cmask=None): g1 = gaussian1D(sigma) g1 /= g1.max() l = g1.shape[0] g2 = np.outer(g1, g1) img2 = conv(img, g2, mode="same") if cmask is not None: img2 *= cmask coeffs = img2[l//2:-(l//2):spacing, l//2:-(l//2):spacing] # view ! return coeffs
def cnnff(self,x): #print x self.layers[0].a={} self.layers[0].a.setdefault(0) self.layers[0].a[0]=x.copy() inputmap=1 n=len(self.layers) for l in range(1,n): if self.layers[l].types=='s': for j in range(inputmap): temp=np.ones((self.layers[l].scale,self.layers[l].scale))/(self.layers[l].scale**2) z=conv(self.layers[l-1].a[j],np.array([temp]), 'valid') z=np.array(z)[:,::self.layers[l].scale,::self.layers[l].scale] if self.layers[l].a==None: self.layers[l].a={} self.layers[l].a.setdefault(j) self.layers[l].a[j] =z if self.layers[l].types=='c': if self.layers[l].a==None: self.layers[l].a={} for j in range(self.layers[l].out): #for each outmaps z = np.zeros(self.layers[l-1].a[0].shape - np.array([0,self.layers[l].kernelsize-1,self.layers[l].kernelsize-1])) for i in range(inputmap): #cumulate from inputmaps z+=conv(self.layers[l-1].a[i],np.array([self.layers[l].k[i][j]]),'valid') self.layers[l].a.setdefault(j) self.layers[l].a[j]=sigmoid(z+self.layers[l].b[j]) inputmap = self.layers[l].out self.fv=None for j in range(len(self.layers[n-1].a)): sa=self.layers[n-1].a[j].shape p=self.layers[n-1].a[j].reshape(sa[0],sa[1]*sa[2]).copy() if (self.fv==None): self.fv=p else: self.fv=np.concatenate((self.fv,p),axis=1) self.fv=self.fv.transpose() self.o=sigmoid(np.dot(self.ffW,self.fv) + self.ffb)
def create_gaussian_vec_ker(vec_size): ''' this function creates a gaussian kernel by convolution of [1 1] with itself, kernel_size times :param kernel_size: number of convolution operations to be performed :return: tuple of the (gaussian coefficients vector, gaussian kernel) ''' if (vec_size < MIN_KER_SIZE): return np.asmatrix(np.array([1])) gaussian_vec = GAUSSIAN_KERNEL for i in range(vec_size - 2): gaussian_vec = conv(GAUSSIAN_KERNEL, gaussian_vec, mode='full') gaussian_ker = conv(gaussian_vec, gaussian_vec.reshape((vec_size, 1)), mode='full') vec_normalize_factor = np.sum(gaussian_vec) ker_normalize_factor = np.sum(gaussian_ker) gaussian_vec = gaussian_vec / vec_normalize_factor gaussian_ker = gaussian_ker / ker_normalize_factor return (gaussian_vec, gaussian_ker)
def ConvFresnel2D(g, x, diam_out, z, inputs, index_of_refraction=1, set_dx=True): lam = inputs[0] / index_of_refraction [dx, diam] = GetDxAndDiam(x) dPhiTol_deg = inputs[3] dx_chirp = (dPhiTol_deg / 180) * lam * z / ( diam + diam_out) # sampling criterion for chirp (factors of pi cancel) if set_dx == False: dx_new = dx elif set_dx == True: # use chirp sampling criterion dx_new = dx_chirp else: # take dx_new to be value of set_dx if str(type(set_dx)) != "<class 'float'>": raise Exception("ConvFresnel2D: set_dx must be a bool or a float.") if set_dx <= 0: raise Exception( "ConvFresnel2D: numerical value of set_dx must be > 0.") dx_new = set_dx if dx != dx_new: # interpolate g onto a grid with spacing of approx dx_new [g, x] = ResampleField2D(g, x, dx_new, inputs, kind='cubic') dx = x[1] - x[0] # make the kernel grid (s) match x as closely as possible ns = int(np.round(diam + diam_out) / dx) # number of points on extended kernel s = np.linspace(-diam / 2 - diam_out / 2 + dx / 2, diam / 2 + diam_out / 2 - dx / 2, ns) # spatial grid of extended kernel ind = np.where(np.abs(s) < diam_out / 2)[0] # get the part of s within the 1D output grid [sx, sy] = np.meshgrid(s, s, indexing='xy') i_out = np.where(np.sqrt(sx * sx + sy * sy) > diam_out / 2) #Calculate Fresnel convoltion kernel, (Goodman 4-16) # Note: the factor p = 1/(lam*z) is applied later # Also note: the factor -1j*np.exp(2j*np.pi*z/lam) causes unwanted oscillations with z kern = np.exp(1j * np.pi * (sx * sx + sy * sy) / (lam * z)) # Fresnel kernel if dx > dx_chirp: # Where does |s| exceed the max step for this dx? s_max = lam * z * dPhiTol_deg / (360 * dx) null_ind = np.where(np.sqrt(sx * sx + sy * sy) > s_max) kern[null_ind[0], null_ind[1]] = 0 h = conv(kern, g, mode='same', method='fft') # h is on the s spatial grid h[i_out[0], i_out[1]] = 0. # zero the field outside the desired region h = h[ind[0]:ind[-1] + 1, ind[0]:ind[-1] + 1] p = 1 / (lam * z) return ([p * h, s[ind]])
def put_gaussians_on_image(shp, sigma, spacing, g_coeffs=None, cmask=None, debug=False): g1 = gaussian1D(sigma) g1 /= g1.max() l = g1.shape[0] g2 = np.outer(g1, g1) res = np.zeros(shp) res[l//2:-(l//2):spacing, l//2:-(l//2):spacing] = 1 if g_coeffs is None else g_coeffs if cmask is not None: res *= cmask # do it before convol, otherwise truncation artefacts ! if debug: print("%d Gaussians used for %s" % (res[res!=0].sum(), str(shp))) res = conv(res, g2, mode="same") return res
def x_out(self, hid): hid = np.pad( hid, ((0, 0), (self.filters[0].shape[0] - 1, self.filters[0].shape[0] - 1), (self.filters[0].shape[1] - 1, self.filters[0].shape[1] - 1)), mode='constant') if self.style == 'reichert': return list( np.sum(np.array([ (conv(np.abs(h), filt, mode='valid'), conv(h, filt, mode='valid')) for (h, filt) in zip(hid, self.adjoint_filters) ]), axis=0)) else: return np.sum(np.array([ conv(h, filt, mode='valid') for (h, filt) in zip(hid, self.adjoint_filters) ]), axis=0)
def blur_spatial(im, kernel_size): ''' this function blurs the given image- im, by convolution with gaussian kernel :param im: the image to be blurred :param kernel_size: the desired gaussian kernel size :return: the blurred image ''' if (kernel_size < MIN_KER_SIZE): return im gaussian_ker = create_gaussian_vec_ker(kernel_size)[1] blurred_img = conv(im, gaussian_ker, mode='same', boundary='wrap') return blurred_img
def findAngle(im, sigma, minThreshold): imin = im.copy() * 255.0 wsize = 5 gausskernel = gaussFilter(sigma, window = wsize) # fx is the filter for vertical gradient # fy is the filter for horizontal gradient # Please note the vertical direction is positive X fx = createFilter([0, 1, 0, 0, 0, 0, 0, -1, 0]) fy = createFilter([ 0, 0, 0, -1, 0, 1, 0, 0, 0]) imout = conv(imin, gausskernel, 'valid') # print "imout:", imout.shape gradxx = conv(imout, fx, 'valid') gradyy = conv(imout, fy, 'valid') gradx = np.zeros(im.shape) grady = np.zeros(im.shape) padx = (imin.shape[0] - gradxx.shape[0]) / 2.0 pady = (imin.shape[1] - gradxx.shape[1]) / 2.0 gradx[padx:-padx, pady:-pady] = gradxx grady[padx:-padx, pady:-pady] = gradyy # Net gradient is the square root of sum of square of the horizontal # and vertical gradients grad = hypot(gradx, grady) theta = arctan2(grady, gradx) xx, yy = where(grad < minThreshold) theta[xx, yy] = 0 grad[xx, yy] = 0 return theta
def conv_der(im): """ derivative of an image using convolution Parameters ---------- :param im Returns ------- :return magnitude of the derivative """ im = im.astype(np.float64) # set der x/y matrix der_x = np.array([[1, 0, -1]]) der_y = np.array(der_x.transpose()) # calculate the derivative to x and y dx = conv(im, der_x, mode='same') dy = conv(im, der_y, mode='same') return np.sqrt(np.abs(dx)**2 + np.abs(dy)**2) # = magnitude
def plot_rewards(n_episodes, rewards, average_range=10): """ Generate plot showing total reward accumulated in each episode. """ smoothed_rewards = (conv(rewards, np.ones(average_range), mode='same') / average_range) fig = plt.figure() plt.plot(range(0, n_episodes, average_range), smoothed_rewards[0:n_episodes:average_range], marker='o', linestyle='--') plt.xlabel('Episodes') plt.ylabel('Total reward') return fig
def __init__(self,imname,sigma,thresHigh = 50,thresLow = 10): self.imin = imread(imname,flatten = True) # Create the gauss kernel for blurring the input image # It will be convolved with the image gausskernel = self.gaussFilter(sigma,5) # fx is the filter for vertical gradient # fy is the filter for horizontal gradient # Please not the vertical direction is positive X fx = self.createFilter([1, 1, 1, 0, 0, 0, -1,-1,-1]) fy = self.createFilter([-1,0,1, -1,0,1, -1,0,1]) imout = conv(self.imin,gausskernel)[1:-1,1:-1] gradx = conv(imout,fx)[1:-1,1:-1] grady = conv(imout,fy)[1:-1,1:-1] # Net gradient is the square root of sum of square of the horizontal # and vertical gradients grad = hypot(gradx,grady) theta = arctan2(grady,gradx) theta = 180 + (180/pi)*theta # Only significant magnitudes are considered. All others are removed x,y = where(grad < 10) theta[x,y] = 0 grad[x,y] = 0 # The angles are quantized. This is the first step in non-maximum # supression. Since, any pixel will have only 4 approach directions. x0,y0 = where(((theta<22.5)+(theta>157.5)*(theta<202.5) +(theta>337.5)) == True) x45,y45 = where( ((theta>22.5)*(theta<67.5) +(theta>202.5)*(theta<247.5)) == True) x90,y90 = where( ((theta>67.5)*(theta<112.5) +(theta>247.5)*(theta<292.5)) == True) x135,y135 = where( ((theta>112.5)*(theta<157.5) +(theta>292.5)*(theta<337.5)) == True) self.theta = theta Image.fromarray(self.theta).convert('L').save('Angle map.jpg') self.theta[x0,y0] = 0 self.theta[x45,y45] = 45 self.theta[x90,y90] = 90 self.theta[x135,y135] = 135 x,y = self.theta.shape temp = Image.new('RGB',(y,x),(255,255,255)) for i in range(x): for j in range(y): if self.theta[i,j] == 0: temp.putpixel((j,i),(0,0,255)) elif self.theta[i,j] == 45: temp.putpixel((j,i),(255,0,0)) elif self.theta[i,j] == 90: temp.putpixel((j,i),(255,255,0)) elif self.theta[i,j] == 45: temp.putpixel((j,i),(0,255,0)) self.grad = grad.copy() x,y = self.grad.shape for i in range(x): for j in range(y): if self.theta[i,j] == 0: test = self.nms_check(grad,i,j,1,0,-1,0) if not test: self.grad[i,j] = 0 elif self.theta[i,j] == 45: test = self.nms_check(grad,i,j,1,-1,-1,1) if not test: self.grad[i,j] = 0 elif self.theta[i,j] == 90: test = self.nms_check(grad,i,j,0,1,0,-1) if not test: self.grad[i,j] = 0 elif self.theta[i,j] == 135: test = self.nms_check(grad,i,j,1,1,-1,-1) if not test: self.grad[i,j] = 0 init_point = self.stop(self.grad, thresHigh) # Hysteresis tracking. Since we know that significant edges are # continuous contours, we will exploit the same. # thresHigh is used to track the starting point of edges and # thresLow is used to track the whole edge till end of the edge. while (init_point != -1): #Image.fromarray(self.grad).show() print 'next segment at',init_point self.grad[init_point[0],init_point[1]] = -1 p2 = init_point p1 = init_point p0 = init_point p0 = self.nextNbd(self.grad,p0,p1,p2,thresLow) while (p0 != -1): #print p0 p2 = p1 p1 = p0 self.grad[p0[0],p0[1]] = -1 p0 = self.nextNbd(self.grad,p0,p1,p2,thresLow) init_point = self.stop(self.grad,thresHigh) # Finally, convert the image into a binary image x,y = where(self.grad == -1) self.grad[:,:] = 0 self.grad[x,y] = 255
def canny(im, sigma, thresHigh = 40, thresLow = 10): ''' Takes an input image in the range [0, 1] and generate a gradient image with edges marked by 1 pixels. ''' imin = im.copy() * 255.0 # Create the gauss kernel for blurring the input image # It will be convolved with the image # wsize should be an odd number wsize = 5 gausskernel = gaussFilter(sigma, window = wsize) # fx is the filter for vertical gradient # fy is the filter for horizontal gradient # Please note the vertical direction is positive X fx = createFilter([0, 1, 0, 0, 0, 0, 0, -1, 0]) fy = createFilter([ 0, 0, 0, -1, 0, 1, 0, 0, 0]) imout = conv(imin, gausskernel, 'valid') # print "imout:", imout.shape gradxx = conv(imout, fx, 'valid') gradyy = conv(imout, fy, 'valid') gradx = np.zeros(im.shape) grady = np.zeros(im.shape) padx = (imin.shape[0] - gradxx.shape[0]) / 2.0 pady = (imin.shape[1] - gradxx.shape[1]) / 2.0 gradx[padx:-padx, pady:-pady] = gradxx grady[padx:-padx, pady:-pady] = gradyy # Net gradient is the square root of sum of square of the horizontal # and vertical gradients grad = hypot(gradx, grady) theta = arctan2(grady, gradx) theta = 180 + (180 / pi) * theta # Only significant magnitudes are considered. All others are removed xx, yy = where(grad < 10) theta[xx, yy] = 0 grad[xx, yy] = 0 # The angles are quantized. This is the first step in non-maximum # supression. Since, any pixel will have only 4 approach directions. x0,y0 = where(((theta<22.5)+(theta>157.5)*(theta<202.5) +(theta>337.5)) == True) x45,y45 = where( ((theta>22.5)*(theta<67.5) +(theta>202.5)*(theta<247.5)) == True) x90,y90 = where( ((theta>67.5)*(theta<112.5) +(theta>247.5)*(theta<292.5)) == True) x135,y135 = where( ((theta>112.5)*(theta<157.5) +(theta>292.5)*(theta<337.5)) == True) theta = theta Image.fromarray(theta).convert('L').save('Angle map.jpg') theta[x0,y0] = 0 theta[x45,y45] = 45 theta[x90,y90] = 90 theta[x135,y135] = 135 x,y = theta.shape temp = Image.new('RGB',(y,x),(255,255,255)) for i in range(x): for j in range(y): if theta[i,j] == 0: temp.putpixel((j,i),(0,0,255)) elif theta[i,j] == 45: temp.putpixel((j,i),(255,0,0)) elif theta[i,j] == 90: temp.putpixel((j,i),(255,255,0)) elif theta[i,j] == 45: temp.putpixel((j,i),(0,255,0)) retgrad = grad.copy() x,y = retgrad.shape for i in range(x): for j in range(y): if theta[i,j] == 0: test = nms_check(grad,i,j,1,0,-1,0) if not test: retgrad[i,j] = 0 elif theta[i,j] == 45: test = nms_check(grad,i,j,1,-1,-1,1) if not test: retgrad[i,j] = 0 elif theta[i,j] == 90: test = nms_check(grad,i,j,0,1,0,-1) if not test: retgrad[i,j] = 0 elif theta[i,j] == 135: test = nms_check(grad,i,j,1,1,-1,-1) if not test: retgrad[i,j] = 0 init_point = stop(retgrad, thresHigh) # Hysteresis tracking. Since we know that significant edges are # continuous contours, we will exploit the same. # thresHigh is used to track the starting point of edges and # thresLow is used to track the whole edge till end of the edge. while (init_point != -1): #Image.fromarray(retgrad).show() # print 'next segment at',init_point retgrad[init_point[0],init_point[1]] = -1 p2 = init_point p1 = init_point p0 = init_point p0 = nextNbd(retgrad,p0,p1,p2,thresLow) while (p0 != -1): #print p0 p2 = p1 p1 = p0 retgrad[p0[0],p0[1]] = -1 p0 = nextNbd(retgrad,p0,p1,p2,thresLow) init_point = stop(retgrad,thresHigh) # Finally, convert the image into a binary image x,y = where(retgrad == -1) retgrad[:,:] = 0 retgrad[x,y] = 1.0 return retgrad
N_squares = 40 W_squares = 20 starts = arange(0, W_squares, 1.0) starts *= N / W_squares for i in starts: for j in starts: grid[i:i+W_squares,j:j+W_squares] = 1 G = fft2(grid) G = fftshift(G) G /= G.max() wider = ones((4,4)) G = conv(G, wider) figure() subplot(1, 2, 1) imshow(grid) axis('off') title('\\textrm{Grid}') subplot(1, 2, 2) M = N/10 imshow(abs(G)[N/2-M:N/2+M, N/2-M:N/2+M], interpolation='nearest') title('\\textrm{Fourier transform}') axis('off')
def roomcomp(impresp, filter, target, ntaps, mixed_phase, opformat, trim, nsthresh, noplot): print "Loading impulse response" # Read impulse response Fs, data = wavfile.read(impresp) data = norm(np.hstack(data)) if trim: print "Removing leading silence" for spos,sval in enumerate(data): if abs(sval)>nsthresh: lzs=max(spos-1,0) ld =len(data) print 'Impulse starts at position ', spos, '/', len(data) print 'Trimming ', float(lzs)/float(Fs), ' seconds of silence' data=data[lzs:len(data)] #remove everything before sample at spos break print "\nSample rate = ", Fs print "\nGenerating correction filter" ### ## Logarithmic pole positioning ### fplog = np.hstack((sp.logspace(sp.log10(20.), sp.log10(200.), 14.), sp.logspace(sp.log10(250.), sp.log10(20000.), 13.))) plog = freqpoles(fplog, Fs) ### ## Preparing data ### # making the measured response minumum-phase cp, minresp = rceps(data) # Impulse response imp = np.zeros(len(data), dtype=np.float64) imp[0]=1.0 # Target outf = [] db = [] if target is 'flat': # Make the target output a bandpass filter Bf, Af = sig.butter(4, 30/(Fs/2), 'high') outf = sig.lfilter(Bf, Af, imp) else: # load target file t = np.loadtxt(target) frq = t[:,0]; pwr = t[:,1] # calculate the FIR filter via windowing method fir = sig.firwin2(501, frq, np.power(10, pwr/20.0), nyq = frq[-1]) # Minimum phase, zero padding cp, outf = rceps(np.append(fir, np.zeros(len(minresp) - len(fir)))) ### ## Filter design ### #Parallel filter design (Bm, Am, FIR) = parfiltid(minresp, outf, plog) # equalized loudspeaker response - filtering the # measured transfer function by the parallel filter equalizedresp = parfilt(Bm, Am, FIR, data) # Equalizer impulse response - filtering a unit pulse equalizer = norm(parfilt(Bm, Am, FIR, imp)) # Windowing with a half hanning window in time domain han = np.hanning(ntaps*2)[-ntaps:] equalizer = han * equalizer[:ntaps] ### ## Mixed-phase compensation ## Based on the paper "Mixed Time-Frequency approach for Multipoint ## Room Rosponse Equalization," by A. Carini et al. ## To use this feature, your Room Impulse Response should have all ## the leading zeros removed. ### if mixed_phase is True: # prototype function hp = norm(np.real(equalizedresp)) # time integration of the human ear is ~24ms # See "Measuring the mixing time in auditoria," by Defrance & Polack hop_size = 0.024 samples = hop_size * Fs bins = np.int(np.ceil(len(hp) / samples)) tmix = 0 # Kurtosis method for b in range(bins): start = np.int(b * samples) end = np.int((b+1) * samples) k = kurtosis(hp[start:end]) if k <= 0: tmix = b * hop_size break # truncate the prototype function taps = np.int(tmix*Fs) print "\nmixing time(secs) = ", tmix, "; taps = ", taps if taps > 0: # Time reverse the array h = hp[:taps][::-1] # create all pass filter phase = np.unwrap(np.angle(h)) H = np.exp(1j*phase) # convert from db to linear mixed = np.power(10, np.real(H)/20.0) # create filter's impulse response mixed = np.real(ifft(mixed)) # convolve and window to desired length equalizer = conv(equalizer, mixed) equalizer = han * equalizer[:ntaps] #data = han * data[:ntaps] #eqresp = np.real(conv(equalizer, data)) else: print "zero taps; skipping mixed-phase computation" if opformat in ('wav', 'wav24'): # Write data wavwrite_24(filter, Fs, norm(np.real(equalizer))) print '\nOutput format is wav24' print 'Output filter length =', len(equalizer), 'taps' print 'Output filter written to ' + filter print "\nUse sox to convert output .wav to raw 32 bit IEEE floating point if necessary," print "or to merge left and right channels into a stereo .wav" print "\nExample: sox leq48.wav -t f32 leq48.bin" print " sox -M le148.wav req48.wav output.wav\n" elif opformat == 'wav32': wavwrite_32(filter, Fs, norm(np.real(equalizer))) print '\nOutput format is wav32' print 'Output filter length =', len(equalizer), 'taps' print 'Output filter written to ' + filter print "\nUse sox to convert output .wav to raw 32 bit IEEE floating point if necessary," print "or to merge left and right channels into a stereo .wav" print "\nExample: sox leq48.wav -t f32 leq48.bin" print " sox -M le148.wav req48.wav output.wav\n" elif opformat == 'bin': # direct output to bin avoids float64->pcm16->float32 conversion by going direct #float64->float32 f = open(filter, 'wb') norm(np.real(equalizer)).astype('float32').tofile(f) f.close() print '\nOutput filter length =', len(equalizer), 'taps' print 'Output filter written to ' + filter else: print 'Output format not recognized, no file generated.' ### ## Plots ### if not noplot: data *= 500 # original loudspeaker-room response tfplot(data, Fs, avg = 'abs') # 1/3 Octave smoothed tfplots(data, Fs, 'r') #tfplot(mixed, Fs, 'r') # equalizer transfer function tfplot(0.75*equalizer, Fs, 'g') # indicating pole frequencies plt.vlines(fplog, -2, 2, color='k', linestyles='solid') # equalized loudspeaker-room response tfplot(equalizedresp*0.01, Fs, avg = 'abs') # 1/3 Octave smoothed tfplots(equalizedresp*0.01, Fs, 'r') # Add labels # May need to reposition these based on input data plt.text(325,30,'Unequalized loudspeaker-room response') plt.text(100,-15,'Equalizer transfer function') plt.text(100,-21,'(Black lines: pole locations)') plt.text(130,-70,'Equalized loudspeaker-room response') a = plt.gca() a.set_xlim([20, 20000]) a.set_ylim([-80, 80]) plt.ylabel('Amplitude (dB)', color='b') plt.xlabel('Frequency (Hz)') plt.grid() plt.legend() plt.show()
def _waveCalibration(self, simpleWvCalib= True, absScale= True, **kwargs): """ """ method = kwargs.pop('method', True) if simpleWvCalib: if absScale: return (np.arange(self.nwv) - self.header['crpix1']) * self.header['cdelt1'] + self.header['crval1'] else: return (np.arange(self.nwv) - self.header['crpix1']) * self.header['cdelt1'] else: if method: if self.band == '6562': line=np.array([6561.097,6564.206]) lamb0=6562.817 dldw=0.019182 elif self.band == '8542': line=np.array([8540.817,8546.222]) lamb0=8542.090 dldw=-0.026252 elif self.band == '5889': line=np.array([5889.951,5892.898]) lamb0=5889.9509 dldw=0.016847 elif self.band == '5434': line=np.array([5434.524,5436.596]) lamb0=5434.5235 dldw=-0.016847 else: if self.band == '6562': line=np.array([6562.817,6559.580]) lamb0=6562.817 dldw=0.019182 elif self.band == '8542': line=np.array([8542.089,8537.930]) lamb0=8542.090 dldw=-0.026252 w = np.arange(self.nwv) wl = np.zeros(2) wc = self.refProfile[20:self.nwv-20].argmin() + 20 lamb = (w - wc) * dldw + lamb0 for i in range(2): mask = np.abs(lamb - line[i]) <= 0.3 wtmp = w[mask] ptmp = conv(self.refProfile[mask], [-1, 2, -1], 'same') mask2 = ptmp[1:-1].argmin() + 1 try: wtmp = wtmp[mask2-3:mask2+4] ptmp = ptmp[mask2-3:mask2+4] except: raise ValueError('Fail to wavelength calibration\n' 'please change the method %s to %s' %(repr(method), repr(not method))) c = np.polyfit(wtmp - np.median(wtmp), ptmp, 2) wl[i] = np.median(wtmp) - c[1]/(2*c[0]) dldw = (line[1] - line[0])/(wl[1] - wl[0]) wc = wl[0] - (line[0] - lamb0)/dldw return (w - wc) * dldw
def computeGradient(im, sigma, canny_edges, thresh, interpolate): ''' Takes an input image in the range [0, 1] and generate a gradient image with edges marked by 1 pixels. ''' imin = im.copy() * 255.0 # Create the gauss kernel for blurring the input image # It will be convolved with the image # wsize should be an odd number wsize = 5 #changed to 7 bc w/e gausskernel = canny.gaussFilter(sigma, window = wsize) # fx is the filter for vertical gradient # fy is the filter for horizontal gradient # Please not the vertical direction is positive X fx = canny.createFilter([0, 1, 0, 0, 0, 0, 0, -1, 0]) fy = canny.createFilter([ 0, 0, 0, -1, 0, 1, 0, 0, 0]) imout = conv(imin, gausskernel, 'same','symm') # print "imout:", imout.shape gradx = conv(imout, fx, 'same','symm') grady = conv(imout, fy, 'same','symm') grad = hypot(gradx, grady) # Only significant magnitudes are considered. All others are removed if(interpolate): samplefraction = 4 #sample only points that are on the lattice of this size # it seems that sampling at smaller intervals makes really cool shapes interpolating_function='thin_plate' #compute thin plate spline, putting sample points on canny edges gsx, gsy = gradx.shape cxx, cyy = where(cannyimg[0:gsx:samplefraction,0:gsy:samplefraction] > 0) cxx = cxx*samplefraction cyy = cyy*samplefraction # the thin plate approximation routines give warnings, ignore them warnings.simplefilter("ignore") zz = gradx[cxx,cyy] mysamples = array([cxx,cyy,zz]).T.reshape(-1,3) xx,yy,zz = mysamples.T thin_plate_x = Rbf(xx,yy,zz,function=interpolating_function) zz = grady[cxx,cyy] mysamples = array([cxx,cyy,zz]).T.reshape(-1,3) xx,yy,zz = mysamples.T thin_plate_y = Rbf(xx,yy,zz,function=interpolating_function) #replace values below threshold with interpolation xx,yy = where(grad < thresh) gradx[xx,yy] = thin_plate_x(xx,yy) grady[xx,yy] = thin_plate_y(xx,yy) theta = arctan2(grady, gradx) #print zz if(not interpolate): xx,yy = where(grad < thresh) theta[xx, yy] = 0 grad[xx, yy] = 0 return (theta, grad)
def wavecalib(band,profile,method=True): """ Calibrate the wavelength for FISS spectrum profile. Parameters ---------- band : str A string to identify the wavelength. Allowable wavelength bands are '6562','8542','5890','5434' profile : ~numpy.ndarray A 1 dimensional numpy array of spectral profile. Method : (optional) bool * Default is True. If true, the reference lines for calibration are the telluric lines. Else if False, the reference lines are the solar absorption lines. Returns ------- wavelength : ~numpy.ndarray Calibrated wavelength. Notes ----- This function is based on the FISS IDL code FISS_WV_CALIB.PRO written by J. Chae, 2013. Example ------- >>> from fisspy.analysis import doppler >>> wv=doppler.wavecalib('6562',profile) """ band=band[0:4] nw=profile.shape[0] if method: if band == '6562': line=np.array([6561.097,6564.206]) lamb0=6562.817 dldw=0.019182 elif band == '8542': line=np.array([8540.817,8546.222]) lamb0=8542.090 dldw=-0.026252 elif band == '5890': line=np.array([5889.951,5892.898]) lamb0=5889.9509 dldw=0.016847 elif band == '5434': line=np.array([5434.524,5436.596]) lamb0=5434.5235 dldw=-0.016847 else: raise ValueError("The wavelength band value is not allowable.\n"+ "Please select the wavelenth "+ "among '6562','8542','5890','5434'") else: if band == '6562': line=np.array([6562.817,6559.580]) lamb0=6562.817 dldw=0.019182 elif band == '8542': line=np.array([8542.089,8537.930]) lamb0=8542.090 dldw=-0.026252 else: raise ValueError("The wavelength band value is not allowable.\n" "Please select the wavelenth " "among '6562','8542','5890','5434'") w=np.arange(nw) wl=np.zeros(2) wc=profile[20:nw-20].argmin()+20 lamb=(w-wc)*dldw+lamb0 for i in range(2): mask=np.abs(lamb-line[i]) <= 0.3 wtmp=w[mask] ptmp=conv(profile[mask],[-1,2,-1],'same') mask2=ptmp[1:-1].argmin()+1 try: wtmp=wtmp[mask2-3:mask2+4] ptmp=ptmp[mask2-3:mask2+4] except: raise ValueError('Fail to wavelength calibration\n' 'please change the method %s to %s' %(repr(method), repr(not method))) c=np.polyfit(wtmp-np.median(wtmp),ptmp,2) wl[i]=np.median(wtmp)-c[1]/(2*c[0]) #local minimum of the profile dldw=(line[1]-line[0])/(wl[1]-wl[0]) wc=wl[0]-(line[0]-lamb0)/dldw wavelength=(w-wc)*dldw return wavelength
def lambdameter(wv, data0, ref_spectrum= False, wvRange = False, hw= 0.03, sp= 5000, wvinput= True): """ Determine the Lambdameter chord center for a given half width or intensity. Parameters ---------- wv : ~numpy.ndarray A Calibrated wavelength. data : ~numpy.ndarray n (n=2 or n=3) dimensional spectral profile data, the last dimension component must be the spectral component, and the size is equal to the size of wv. wvinput : bool There are two cases. * Case wvinput==True hw : float A half width of the horizontal line segment. Returns ------- wc : nd ndarray n dimensional array of central wavelength values. intc : nd ndarray n dimensional array of intensies of the line segment.\\ * Case wvinput==False sp : float An intensity of the horiznotal segment. Returns ------- wc : nd ndarray n dimensional array of central wavelength values. hwc : nd ndarray n dimensional array of half widths of the line segment. Notes ----- This function is based on the IDL code BISECTOR_D.PRO written by J. Chae. Example ------- >>> from fisspy.analysis import doppler >>> wc, inten = doppler.labdameter(wv,data,0.2) """ shape=data0.shape nw=shape[-1] reshape=shape[:-1] dkern = np.array([[-1, 1, 0, 1, -1]]) rspec = np.any(ref_spectrum) ndim = data0.ndim wvoffset = 0 dwv = wv[1]-wv[0] if rspec and data0.ndim == 3: refSpec = conv(ref_spectrum , dkern[0],'same') refSpec[:2] = refSpec[-2:] = 0 refSpec = refSpec * np.ones((4,1)) data2d = conv(data0.mean(0), dkern, 'same') data2d[:,:2] = data2d[:,-2:] = 0 data = data2d * np.ones((4, 1, 1)) # data[:,:,:2] = data[:,:,-2:] = 0 dataT = data.transpose((1, 0, 2)) yoff, xoff, cor = alignoffset(dataT, refSpec, cor= True) wvoffset = (xoff*(wv[1]-wv[0])) * (cor > 0.7) elif not rspec and ndim == 3: wvoffset = np.zeros(shape[1]) elif ndim == 1 or ndim >=4: ValueError('The dimension of data0 must be 2 or 3.') if wv.shape[0] != nw: raise ValueError('The number of elements of wv and ' 'the number of elements of last axis for data are not equal.') if np.any(wvRange): ss = np.logical_and(wv >= wvRange[0], wv <= wvRange[1]) nw = ss.sum() data0 = data0[:,:,ss].copy() wv = wv[ss].copy() na=int(data0.size/nw) data=data0.reshape((na,nw)) s=data.argmin(axis=-1) if wvinput and hw == 0.: raise ValueError('The half-width value must be greater than 0.') # fna=range(na) # wtmp=wv[np.array((s-5,s-4,s-3,s-2,s-1,s,s+1,s+2,s+3,s+4,s+5))] # mwtmp=np.median(wtmp,axis=0) # sp0=np.array([data[i,s[i]-5:s[i]+6] for i in fna]) # c=np.array([scipy.polyfit(wtmp[:,i]-mwtmp[i],sp0[i,:],2) for i in fna]) # wc=mwtmp-c[:,1]/(2*c[:,0]) # p=[scipy.poly1d(c[i,:]) for i in fna] # intc=np.array([p[i](wc[i]-mwtmp[i]) for i in fna]) # wc=wc.reshape(reshape).T # intc=intc.reshape(reshape).T # return wc, intc posi0=np.arange(na) smin=[0,wv[0]] smax=[na-1,wv[-1]] order=[na,len(wv)] if wvinput: interp=LinearSpline(smin,smax,order,data) wl=np.array((posi0,wv[s]-hw)).T; wr=np.array((posi0,wv[s]+hw)).T intc=0.5*(interp(wl)+interp(wr)) else: intc=np.ones(na)*sp wc=np.zeros(na) hwc=np.zeros(na) ref=1 rep=0 s0=s.copy() more=data[posi0,s0]>100 while ref > 0.00001 and rep <6: sp1=data-intc[:,None] comp=sp1[:,0:nw-1]*sp1[:,1:nw] s=comp[more] <=0. nsol=s.sum(axis=1) j=nsol//2 whl=nsol.cumsum()-nsol+j-1 whr=nsol.cumsum()-nsol+j whp, whs=np.where(s) l=whs[whl] r=whs[whr] posi=posi0[more] wl0=wv[l]-dwv/(sp1[posi,l+1]-sp1[posi,l])*sp1[posi,l] wr0=wv[r]-dwv/(sp1[posi,r+1]-sp1[posi,r])*sp1[posi,r] wc[more]=0.5*(wl0+wr0) hwc[more]=0.5*np.abs(wr0-wl0) if wvinput: wl=np.array((posi,wc[more]-hw)).T; wr=np.array((posi,wc[more]+hw)).T intc[more]=0.5*(interp(wl)+interp(wr)) ref0=np.abs(hwc-hw) ref=ref0.max() more=(ref0>0.00001)*(data[posi0,s0]>100) else: ref=0 rep+=1 wc = wc.reshape(reshape) - wvoffset if wvinput: intc=intc.reshape(reshape) return wc, intc else: hwc=hwc.reshape(reshape) return wc, hwc