def create_basist(self, block=15, n=10): npt = (n - 1) * block + 1 basist = zeros([npt, n]) x = arange(npt) / float(block) for jx in range(n): basist[:, jx] = signal.bspline(x - jx, 2) # end-effects, it's important that the sum is flat basist[:, 0] += signal.bspline(x + 1, 2) basist[:, n - 1] += signal.bspline(x - n, 2) return basist
def find_peak_start(input, treshold=0.001, peak_length=15): input = numpy.abs(numpy.gradient(signal.bspline(input, 25))) # Control parameters input_treshold = numpy.nanmax(input) * treshold input_length = input.shape[0] recording = False start_x = 0 stop_x = 0 # Walk from start to end. When the current value exceeds threshold, # start recording. for i in range(0, input_length): if recording: if input[i] > treshold: stop_x = i if (stop_x - start_x) > peak_length: return start_x else: recording = False else: if input[i] > treshold: start_x = i recording = True # Nothing found return 0
def main(): from scipy.signal import bspline orders = [1, 2, 3] particle_positions = 3. + np.arange(0, 1., 0.1) bsplines = [] path = sys.argv[1] for centering in ["primal", "dual"]: for order in orders: filename = os.path.join(path, f"bsplines_{order}_{centering}.dat") node_splines = np.zeros((order + 1, particle_positions.size), dtype=np.int32) splines_val = np.zeros((order + 1, particle_positions.size), dtype=np.float64) for ipos, pos in enumerate(particle_positions): node_splines[:, ipos] = get_nodes(pos, order, centering) # loop on all nodes and calculate the spline at the node # from the current particle position with open(filename, 'wb') as f: for ipos, pos in enumerate(particle_positions): if centering == "dual": pos -= .5 splines_val[:, ipos] = bspline(node_splines[:, ipos] - pos, order) print(ipos, node_splines[:, ipos], splines_val[:, ipos]) node_splines[:, ipos].tofile(f) splines_val[:, ipos].tofile(f)
def main(): orders = [1,2,3] particle_positions = 3. + np.arange(0,1.,0.1) bsplines = [] path = sys.argv[1] for order in orders: filename = path+os.path.sep + "bsplines_{}.dat".format(order) node_splines = np.zeros((order+1, particle_positions.size), dtype=np.int32) splines_val = np.zeros((order+1, particle_positions.size), dtype=np.float64) for ipos, pos in enumerate(particle_positions): node_splines[:,ipos] = get_nodes(pos, order) # loop on all nodes and calculate the spline at the node # from the current particle position with open(filename, 'wb') as f: for ipos, pos in enumerate(particle_positions): splines_val[:,ipos] = bspline(node_splines[:, ipos] - pos, order) print(ipos, node_splines[:, ipos], splines_val[:,ipos]) node_splines[:, ipos].tofile(f) splines_val[:, ipos].tofile(f)
def __call__(self, d): sfact = self.s // d + 1 #w = np.bartlett(2*sfact+1) w = signal.bspline(np.linspace(-2, 2, 4 * sfact + 1), 3) fh = ndi.convolve1d(self.mat, w, axis=0, mode='constant') fh = ndi.convolve1d(fh, w, axis=1, mode='constant') sh = ndi.zoom(fh, d / self.s, order=3, prefilter=False) return sh
def __basis(self, order=4, divisions=4): """ Follows the derivations in: Kybic, J. and Unser, M. (2003). Fast parametric elastic image registration. IEEE Transactions on Image Processing, 12(11), 1427-1442. Computes the spline tensor product and stores the products, as basis vectors. @param order: b-spline order. @param division: number of spline knots. """ shape = self.coordinates.tensor[0].shape grid = self.coordinates.tensor spacing = shape[1] / divisions xKnots = shape[1] / spacing yKnots = shape[0] / spacing Qx = np.zeros((grid[0].size, xKnots)) Qy = np.zeros((grid[0].size, yKnots)) for index in range(0, xKnots): bx = signal.bspline( grid[1] / spacing - index, order) Qx[:,index] = bx.flatten() for index in range(0, yKnots): by = signal.bspline( grid[0] / spacing - index, order) Qy[:,index] = by.flatten() basis = [] for j in range(0,xKnots): for k in range(0, yKnots): basis.append(Qx[:,j]*Qy[:,k]) self.basis = np.array(basis).T
def __basis(self, order=4, divisions=5): """ Computes the spline tensor product and stores the products, as basis vectors. Parameters ---------- order: int B-spline order, optional. divisions: int, optional. Number of spline knots. """ shape = self.coordinates.tensor[0].shape grid = self.coordinates.tensor spacing = shape[1] / divisions xKnots = shape[1] / spacing yKnots = shape[0] / spacing Qx = np.zeros((grid[0].size, xKnots)) Qy = np.zeros((grid[0].size, yKnots)) for index in range(0, xKnots): bx = signal.bspline(grid[1] / spacing - index, order) Qx[:, index] = bx.flatten() for index in range(0, yKnots): by = signal.bspline(grid[0] / spacing - index, order) Qy[:, index] = by.flatten() basis = [] for j in range(0, xKnots): for k in range(0, yKnots): basis.append(Qx[:, j] * Qy[:, k]) self.basis = np.array(basis).T
def __basis(self, order=4, divisions=4): """ Computes the spline tensor product and stores the products, as basis vectors. Parameters ---------- order: int B-spline order, optional. divisions: int, optional. Number of spline knots. """ shape = self.coordinates.tensor[0].shape grid = self.coordinates.tensor spacing = shape[1] / divisions xKnots = shape[1] / spacing yKnots = shape[0] / spacing Qx = np.zeros((grid[0].size, xKnots)) Qy = np.zeros((grid[0].size, yKnots)) for index in range(0, xKnots): bx = signal.bspline( grid[1] / spacing - index, order) Qx[:,index] = bx.flatten() for index in range(0, yKnots): by = signal.bspline( grid[0] / spacing - index, order) Qy[:,index] = by.flatten() basis = [] for j in range(0,xKnots): for k in range(0, yKnots): basis.append(Qx[:,j]*Qy[:,k]) self.basis = np.array(basis).T
def _shape(self, x, y): """Private method calculate b-spline value for particles on x-position on grid Keyword arguments: ------------------ x -- position on grid (numpy.array) y -- particle(s) position (numpy.array) Return: ------- bspline (numpy.array of float) of B-spline(x,order) value representing kernel """ ksi = (x - y) / self.particles.support_scale return sb.bspline(ksi, self.spline_order)
def interpolate(img_stack, slices, method='bcspline'): """interpolate a single frame. method can be none, bilinear, lanczos3, or bcspline""" #TODO: make this more efficient!! if method == 'none': return img_stack #create the filter based on the type of interpolation: if method == 'bcspline': #reconstruction/interpolation filter #3rd order bspline function filt = signal.bspline([-1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5], 3) elif method == 'bilinear': filt = [0.5, 1.0, 0.5] elif method == 'lanczos3': #x = linspace(-2.5,2.5,11) #evenly spaced from -2.5 to 2.5 by 0.5 increments #filt = sinc(x/3)*sinc(x) filt = [ 2.44565217e-02, 0, -1.35869565e-01, 0, 6.11413043e-01, 1, 6.11413043e-01, 0, -1.35869565e-01, 0, 2.44565217e-02 ] #allocate the output array: #img_stack.shape is (w/2, h/2, 4) #we're going to expand to (w,h,4): s = list(img_stack.shape) s[:2] = np.multiply(s[:2], 2) #element-wise multiply (w,h,4) #interpolated result: interp_stack = zeros(s) #interpolation coefficients for intermediate steps c_jk = zeros(s[:2]) #(w,h) #loop over last dimension (i0,i90,...) for j in xrange(s[-1]): #zero the coefficients c_jk[...] = 0.0 #get coefficients if method in ['bilinear', 'lanczos3']: #coefficients are just the image slices c_jk[slices[j]] = img_stack[..., j] elif method == 'bcspline': #coefficients are bicubic spline coefficients for slice c_jk[slices[j]] = signal.cspline2d(img_stack[..., j]) #convolve (filters are seperable, so we can use sepfir2d) interp_stack[..., j] = signal.sepfir2d(c_jk, filt, filt) #return interpolated image: return interp_stack
def aggregate_windows(self, window_seq, order=2, **kwargs): """ :param window_seq: :param order: :param kwargs: :return: """ coef = 30 for window in window_seq: splined_window = bspline( 1 - np.array(window)[::coef], n=order, ) for win_index, win_item in enumerate(splined_window): for i in range(coef): yield win_item
def pair_eval(self, X, Y): """ Evaluate k(x1, y1), k(x2, y2), ... Parameters ---------- X, Y : n x 1 numpy array Return ------- a numpy array with length n """ (n1, d1) = X.shape (n2, d2) = Y.shape assert d1 == 1, 'd1 must be 1' assert d2 == 1, 'd2 must be 1' diff = (X - Y) / self.width Kvec = sig.bspline(diff, 1) return Kvec
def pair_eval(self, X, Y): """ Evaluate k(x1, y1), k(x2, y2), ... Parameters ---------- X, Y : n x 1 numpy array Return ------- a numpy array with length n """ (n1, d1) = X.shape (n2, d2) = Y.shape assert d1==1, 'd1 must be 1' assert d2==1, 'd2 must be 1' diff = old_div((X-Y),self.width) Kvec = sig.bspline( diff , 1) return Kvec
def eval(self, X1, X2): """ Evaluate the triangular kernel on the two 2d numpy arrays. Parameters ---------- X1 : n1 x 1 numpy array X2 : n2 x 1 numpy array Return ------ K : a n1 x n2 Gram matrix. """ (n1, d1) = X1.shape (n2, d2) = X2.shape assert d1 == 1, 'd1 must be 1' assert d2 == 1, 'd2 must be 1' diff = (X1 - X2.T) / self.width K = sig.bspline(diff, 1) return K
def eval(self, X1, X2): """ Evaluate the triangular kernel on the two 2d numpy arrays. Parameters ---------- X1 : n1 x 1 numpy array X2 : n2 x 1 numpy array Return ------ K : a n1 x n2 Gram matrix. """ (n1, d1) = X1.shape (n2, d2) = X2.shape assert d1==1, 'd1 must be 1' assert d2==1, 'd2 must be 1' diff = old_div((X1-X2.T),self.width) K = sig.bspline( diff , 1) return K
def eval(self, X1, X2): """ Evaluate the triangular kernel on the two 2d numpy arrays. Parameters ---------- X1 : n1 x 1 numpy array X2 : n2 x 1 numpy array Return ------ K : a n1 x n2 Gram matrix. """ d1 = X1.shape[1] if d1 != 1: raise ValueError("The X1 dimension (_, {}) must be 1".format(d1)) d2 = X2.shape[1] if d2 != 1: raise ValueError("The X2 dimension (_, {}) must be 1".format(d2)) diff = X1 - X2.T np.divide(diff, self.width, out=diff) return signal.bspline(diff, 1)
def test_splines(self): x = np.linspace(-10, 10, 10000) for degree in range(9): np.testing.assert_allclose(signal.bspline(x, degree), bsplines.bspline(x, degree))
return None n_b = n + 1 n = (n + 1) / h b = [0 for _ in np.arange(-1 * n / 2, (n / 2) + 0.5, 0.5)] x = [i * h for i in np.arange(-1 * n / 2, (n / 2) + 0.5, 0.5)] if n == 1: for i in range(0, len(x)): b[i] = b_n_first(x[i]) return x, b for i in range(0, len(x)): b[i] = b_n(x[i], n_b) return x, b if __name__ == '__main__': x_10, y_10 = beta_spline(10) x_15, y_15 = beta_spline(15) y_signal = signal.bspline(x_15, 15) sns.set() fig, axs = plt.subplots(2, figsize=(WIDTH, HEIGHT)) axs[0].plot(x_10, y_10, color='red') axs[0].plot(x_15, y_15, color='green') axs[0].set_title('Beta Splines') axs[0].set_xlabel('X') axs[0].set_ylabel('Y') axs[0].legend(['Spline (n=10)', 'Spline (n=15)']) axs[1].plot(x_15, y_signal, color='black') axs[1].set_xlabel('X') axs[1].set_ylabel('Y') axs[1].legend(['Spline (scipy.gignal, n=15)']) plt.show()
def featgrid(self, center, value, type_='fast_gaussian'): """Map an individual feature (atomic or residue) on the grid. Args: center (list(float)): position of the feature center value (float): value of the feature type_ (str, optional): method to map Returns: np.array: Mapped feature Raises: ValueError: Description """ # shortcut for th center x0, y0, z0 = center sigma = np.sqrt(1. / 2) beta = 0.5 / (sigma**2) # simple Gaussian if type_ == 'gaussian': dd = np.sqrt((self.xgrid - x0)**2 + (self.ygrid - y0)**2 + (self.zgrid - z0)**2) dd = value * np.exp(-beta * dd) return dd # fast gaussian elif type_ == 'fast_gaussian': cutoff = 5. * beta dd = np.sqrt((self.xgrid - x0)**2 + (self.ygrid - y0)**2 + (self.zgrid - z0)**2) dgrid = np.zeros(self.npts) dgrid[dd < cutoff] = value * np.exp(-beta * dd[dd < cutoff]) return dgrid # Bsline elif type_ == 'bspline': spline_order = 4 spl = bspline((self.xgrid - x0) / self.res[0], spline_order) \ * bspline((self.ygrid - y0) / self.res[1], spline_order) \ * bspline((self.zgrid - z0) / self.res[2], spline_order) dd = value * spl return dd # nearest neighbours elif type_ == 'nearest': # distances dx = np.abs(self.x - x0) dy = np.abs(self.y - y0) dz = np.abs(self.z - z0) # index indx = np.argsort(dx)[:2] indy = np.argsort(dy)[:2] indz = np.argsort(dz)[:2] # weight wx = dx[indx] wx /= np.sum(wx) wy = dy[indy] wy /= np.sum(wy) wz = dx[indz] wz /= np.sum(wz) # define the points indexes = [indx, indy, indz] points = list(itertools.product(*indexes)) # define the weight W = [wx, wy, wz] W = list(itertools.product(*W)) W = [np.sum(iw) for iw in W] # put that on the grid dgrid = np.zeros(self.npts) for w, pt in zip(W, points): dgrid[pt[0], pt[1], pt[2]] = w * value return dgrid # default else: raise ValueError(f'Options not recognized for the grid {type_}')
import numpy as np import matplotlib.pyplot as plt import scipy.signal as sps import scipy.interpolate as spi # plot cubic cardinal B-spline (knots 0, 1, 2, 3, 4) p = 3 xx = np.linspace(0, p + 1, 100) yy = sps.bspline(xx - (p + 1) / 2, p) plt.plot(xx, yy) plt.show() # plot cubic non-uniform spline (m=5 DOFs) xi = [0, 1, 3, 4, 6, 7, 8, 10, 11] c = [2, -1, 1, 0, 1] s = spi.BSpline(xi, c, p) m = len(c) xx = np.linspace(xi[p], xi[m]) yy = s(xx) plt.plot(xx, yy) plt.show()
def spline_fit(x, y, weights, xfit): """ Fit a cubic b-spline to y vs. x with weights and full error propagation. Return fit with diagonalized errors. Inputs: x, y, weights : numpy arrays sorted by ascending x Returns 1D arrays: coadd_y[] coadd_ivar[] Where coadd_ivar is the diagonal inverse variance of coadd_y. """ #- Setup cubic b-spline basis matrix: y = A coeff t0 = time() ny = len(y) dxfit = N.gradient(xfit) A = N.zeros( (ny, len(xfit)) ) for i in range(A.shape[0]): A[i] = bspline((x[i] - xfit)/dxfit, 3) t0 = timeit("Setup A", t0) #- Convert to sparse matrices A = scipy.sparse.dia_matrix(A) W = spdiags(weights, 0, ny, ny) t0 = timeit("Sparsify A", t0) #- Generate inverse covariance matrix iCovCoeff = A.T.dot(W.dot(A)) #- Solve "y = A coeff" with weights -> (A.T W) y = (A.T W A) coeff wy = A.T.dot(W.dot(y)) t0 = timeit("Apply weights", t0) # coeff = scipy.sparse.linalg.lsqr(iCovCoeff, wy)[0] # t0 = timeit("Solve", t0) #- Solve with banded matrices iCovDiag = iCovCoeff.todia().data[-1::-1, :] #- have to flip for solver ndiag = iCovDiag.shape[0]/2 coeff = scipy.linalg.solve_banded((ndiag, ndiag), iCovDiag, wy) t0 = timeit("Solve", t0) #- Evaluate b-spline solution at xfit B = N.zeros( (len(xfit), len(xfit)) ) for i in range(B.shape[0]): B[i] = bspline((xfit[i] - xfit)/dxfit, 3) coadd = B.dot(coeff) t0 = timeit("Evaluate", t0) ### This is the expensive step as matrices get larger ### could use eig_banded and invert with that #- Convert iCov for coefficients into iCov for the coadd itself #- coadd = B coeff #- CovCoadd = B CovCoeff B.T #- iCovCoadd = iB.T iCovCoeff iB, since B is square and invertable iB = N.linalg.inv(B) iCovCoadd = iB.T.dot( iCovCoeff.dot(iB) ) t0 = timeit("Get iCov(coadd)", t0) ### This is the next most expensive step as matrices get larger #- Diagonalize errors try: R, coivar = resolution_from_icov(iCovCoadd) Rc = R.dot(coadd) except: print "ERROR: Unable to find R for range", xfit[0], xfit[1] return N.zeros(len(coadd)), N.zeros(len(coadd)) t0 = timeit("Diagonalize", t0) return Rc, coivar
def key_points(face, d_nose_x1=30, d_nose_x2=5, d_nose_y=5, d_lip_y1=25, d_lip_y2=70, d_lip_y3=4, d_lip_x1=45, d_chin_x=3, d_chin_y1=10, d_chin_y2=75, d_eye_x=2, d_eye_y=50): """ Rotate and zoom the face to create a full frame face. This is based on the fact that the nose is the highest point of the picture """ # We apply surfature to calculate the first and second derivates K, H, Pmax, Pmin = surfature(face) # Remove all key points face.key_points.clear() # # Nose # nose_x, nose_y = max_xy(face.Z) face.key_points["nose"] = (nose_x, nose_y) # # Nose left and right # nose_left = Pmin[(nose_y - d_nose_y):(nose_y + d_nose_y), (nose_x - d_nose_x1):(nose_x - d_nose_x2)] nose_right = Pmin[(nose_y - d_nose_y):(nose_y + d_nose_y), (nose_x + d_nose_x2):(nose_x + d_nose_x1)] nose_left_x, nose_left_y = min_xy(nose_left, offset_x=(nose_x - d_nose_x1), offset_y=(nose_y - d_nose_y)) nose_right_x, nose_right_y = min_xy(nose_right, offset_x=(nose_x + d_nose_x2), offset_y=(nose_y - d_nose_y)) face.key_points["nose_left"] = (nose_left_x, nose_left_y) face.key_points["nose_right"] = (nose_right_x, nose_right_y) # # Upper, lower, left right lip # lip_y = numpy.nanargmax(Pmax[(nose_y + d_lip_y1):(nose_y + d_lip_y2), nose_x]) + (nose_y + d_lip_y1) lip_left = Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), (nose_x - d_lip_x1):nose_x] lip_right = Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), nose_x:(nose_x + d_lip_x1)] lip_left_x = find_peak_start(numpy.sum(lip_left, axis=0)) + (nose_x - d_lip_x1) lip_left_y = numpy.nanargmax(Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), lip_left_x]) + (lip_y - d_lip_y3) lip_right_x = find_peak_stop(numpy.sum(lip_right, axis=0)) + nose_x lip_right_y = numpy.nanargmax(Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), lip_right_x]) + (lip_y - d_lip_y3) face.key_points['lip'] = (nose_x, lip_y) face.key_points['lip_left'] = (lip_left_x, lip_left_y) face.key_points['lip_right'] = (lip_right_x, lip_right_y) # # Chin # chin = numpy.gradient( signal.bspline(face.Z[(lip_y + d_chin_y1):, nose_x], 25)) chin_x, chin_y = nose_x, numpy.nanargmin(chin) + (lip_y + d_chin_y1) face.key_points["chin"] = (chin_x, chin_y) # # Eyes # eye_left = Pmax[nose_left_y - d_eye_y:nose_left_y + d_eye_y, nose_left_x - d_eye_x:nose_left_x + d_eye_x] eye_right = Pmax[nose_right_y - d_eye_y:nose_right_y + d_eye_y, nose_right_x - d_eye_x:nose_right_x + d_eye_x] eye_left_x, eye_left_y = max_xy(eye_left, nose_left_x - d_eye_x, d_eye_y) eye_right_x, eye_right_y = max_xy(eye_right, nose_right_x - d_eye_x, d_eye_y) face.key_points["eye_left"] = (eye_left_x, eye_left_y) face.key_points["eye_right"] = (eye_right_x, eye_right_y) # # Nose face border # nose_line = numpy.gradient(face.Z[nose_y, :]) border_nose_left_x, border_nose_left_y = numpy.nanargmax( nose_line[:lip_left_x - 10]), nose_y border_nose_right_x, border_nose_right_y = numpy.nanargmin( nose_line[lip_right_x:]) + lip_right_x + 10, nose_y face.key_points["border_nose_left"] = (border_nose_left_x, border_nose_left_y) face.key_points["border_nose_right"] = (border_nose_right_x, border_nose_right_y) # # Lip face border # lip_line = numpy.gradient(face.Z[lip_y, :]) border_lip_left_x, border_lip_left_y = numpy.nanargmax( lip_line[:lip_left_x - 10]), lip_y border_lip_right_x, border_lip_right_y = numpy.nanargmin( lip_line[lip_right_x:]) + lip_right_x + 10, lip_y face.key_points["border_lip_left"] = (border_lip_left_x, border_lip_left_y) face.key_points["border_lip_right"] = (border_lip_right_x, border_lip_right_y) # # Forehead border # forehead_line = numpy.gradient(face.Z[nose_y - (chin_y - nose_y), :]) border_forehead_left_x, border_forehead_left_y = numpy.nanargmax( forehead_line[:lip_left_x - 10]), nose_y - (chin_y - nose_y) border_forehead_right_x, border_forehead_right_y = numpy.nanargmin( forehead_line[lip_right_x:]) + lip_right_x + 10, nose_y - (chin_y - nose_y) face.key_points["border_forehead_left"] = (border_forehead_left_x, border_forehead_left_y) face.key_points["border_forehead_right"] = (border_forehead_right_x, border_forehead_right_y)
def key_points(face, d_nose_x1=30, d_nose_x2=5, d_nose_y=5, d_lip_y1=25, d_lip_y2=70, d_lip_y3=4, d_lip_x1=50, d_chin_x=3, d_chin_y1=50, d_chin_y2=75, d_eye_x=2, d_eye_y=50): """ Rotate and zoom the face to create a full frame face. This is based on the fact that the nose is the highest point of the picture """ # We apply surfature to calculate the first and second derivates K, H, Pmax, Pmin = surfature(face) # Remove all key points face.key_points.clear() # # Nose # nose_x, nose_y = max_xy(face.Z) face.key_points["nose"] = (nose_x, nose_y) # # Nose left and right # nose_left = Pmin[(nose_y - d_nose_y):(nose_y + d_nose_y), (nose_x - d_nose_x1):(nose_x - d_nose_x2)] nose_right = Pmin[(nose_y - d_nose_y):(nose_y + d_nose_y), (nose_x + d_nose_x2):(nose_x + d_nose_x1)] nose_left_x, nose_left_y = min_xy(nose_left, offset_x=(nose_x - d_nose_x1), offset_y=(nose_y - d_nose_y)) nose_right_x, nose_right_y = min_xy(nose_right, offset_x=(nose_x + d_nose_x2), offset_y=(nose_y - d_nose_y)) face.key_points["nose_left"] = (nose_left_x, nose_left_y) face.key_points["nose_right"] = (nose_right_x, nose_right_y) # # Upper, lower, left right lip # lip_y = numpy.nanargmax(Pmax[(nose_y + d_lip_y1):(nose_y + d_lip_y2), nose_x]) + (nose_y + d_lip_y1) lip_left = Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), (nose_x - d_lip_x1):nose_x] lip_right = Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), nose_x:(nose_x + d_lip_x1)] lip_left_x = find_peak_start(numpy.sum(lip_left, axis=0)) + (nose_x - d_lip_x1) lip_left_y = numpy.nanargmax(Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), lip_left_x]) + (lip_y - d_lip_y3) lip_right_x = find_peak_stop(numpy.sum(lip_right, axis=0)) + nose_x lip_right_y = numpy.nanargmax(Pmax[(lip_y - d_lip_y3):(lip_y + d_lip_y3), lip_right_x]) + (lip_y - d_lip_y3) face.key_points['lip'] = (nose_x, lip_y) face.key_points['lip_left'] = (lip_left_x, lip_left_y) face.key_points['lip_right'] = (lip_right_x, lip_right_y) # # Chin # chin = numpy.gradient(signal.bspline(face.Z[(lip_y + d_chin_y1):, nose_x], 25)) chin_x, chin_y = nose_x, numpy.nanargmin(chin) + (lip_y + d_chin_y1) face.key_points["chin"] = (chin_x, chin_y) # # Eyes # eye_left = Pmax[d_eye_y:nose_left_y - d_eye_y, nose_left_x - d_eye_x:nose_left_x + d_eye_x] eye_right = Pmax[d_eye_y:nose_right_y - d_eye_y, nose_right_x - d_eye_x:nose_right_x + d_eye_x] eye_left_x, eye_left_y = max_xy(eye_left, nose_left_x - d_eye_x, d_eye_y) eye_right_x, eye_right_y = max_xy(eye_right, nose_right_x - d_eye_x, d_eye_y) face.key_points["eye_left"] = (eye_left_x, eye_left_y) face.key_points["eye_right"] = (eye_right_x, eye_right_y) # # Nose face border # nose_line = numpy.gradient(face.Z[nose_y, :]) border_nose_left_x, border_nose_left_y = numpy.nanargmax(nose_line[:lip_left_x - 10]), nose_y border_nose_right_x, border_nose_right_y = numpy.nanargmin(nose_line[lip_right_x + 10:]) + lip_right_x + 10, nose_y face.key_points["border_nose_left"] = (border_nose_left_x, border_nose_left_y) face.key_points["border_nose_right"] = (border_nose_right_x, border_nose_right_y) # # Lip face border # lip_line = numpy.gradient(face.Z[lip_y, :]) border_lip_left_x, border_lip_left_y = numpy.nanargmax(lip_line[:lip_left_x - 10]), lip_y border_lip_right_x, border_lip_right_y = numpy.nanargmin(lip_line[lip_right_x + 10:]) + lip_right_x + 10, lip_y face.key_points["border_lip_left"] = (border_lip_left_x, border_lip_left_y) face.key_points["border_lip_right"] = (border_lip_right_x, border_lip_right_y) # # Forehead border # forehead_line = numpy.gradient(face.Z[nose_y - (chin_y - nose_y), :]) border_forehead_left_x, border_forehead_left_y = numpy.nanargmax(forehead_line[:lip_left_x - 10]), nose_y - (chin_y - nose_y) border_forehead_right_x, border_forehead_right_y = numpy.nanargmin(forehead_line[lip_right_x + 10:]) + lip_right_x + 10, nose_y - (chin_y - nose_y) face.key_points["border_forehead_left"] = (border_forehead_left_x, border_forehead_left_y) face.key_points["border_forehead_right"] = (border_forehead_right_x, border_forehead_right_y)