def shear(a,dl,method,y,x): if method=="v1" : return geometric_transform(a,mapping_v1,(y,x+dl),order=5,mode='nearest',extra_arguments=(y,x,dl))[:, dl/2:-dl/2] elif method=="v2" : return geometric_transform(a,mapping_v2,(y,x+dl),order=5,mode='nearest',extra_arguments=(y,x,dl))[:, dl/2:-dl/2] elif method=="h1" : return geometric_transform(a,mapping_h1,(y+dl,x),order=5,mode='nearest',extra_arguments=(y,x,dl))[dl/2:-dl/2, :] elif method=="h2" : return geometric_transform(a,mapping_h2,(y+dl,x),order=5,mode='nearest',extra_arguments=(y,x,dl))[dl/2:-dl/2, :]
def polar_trfm(Im, ntheta, nrad, rmax): #Polar Transform rows, cols = Im.shape cx = (rows + 1) / 2 cy = (cols + 1) / 2 # rmax=(rows-1)/2 # deltatheta = 2 * np.pi/(ntheta) # deltarad = rmax/(nrad-1) theta_int = np.linspace(0, 2 * np.pi, ntheta) r_int = np.linspace(0, rmax, nrad) theta, radius = np.meshgrid(theta_int, r_int) def transform(coords): theta = 2.0 * np.pi * coords[1] / ntheta radius = rmax * coords[0] / nrad i = cx + radius * np.cos(theta) j = radius * np.sin(theta) + cy return i, j # xi = radius * np.cos(theta) + cx # yi = radius * np.sin(theta) + cy PolIm = geometric_transform(Im.astype(float), transform, order=1, mode='constant', output_shape=(nrad, ntheta)) PolIm[np.isnan(PolIm[:])] = 0 return PolIm
def do_geo_warp(image, field): def mapper(t): x, y = t tx, ty = field[x, y] return x + tx, y + ty return geometric_transform(image, mapper, mode='nearest')
def resample_field(data_src, bbox_src, shape_dst, bbox_dst, order=2, mode='constant', cval=0.): #see http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.interpolation.geometric_transform.htm bbox0, bbox1 = np.asarray(bbox_dst), np.asarray(bbox_src) o_ = (bbox0[0] - bbox1[0]) / (bbox1[1] - bbox1[0]) s_ = (bbox0[1] - bbox0[0]) / (bbox1[1] - bbox1[0]) s_ /= np.asarray(shape_dst) - 1 o_ *= np.asarray(data_src.shape) - 1 s_ *= np.asarray(data_src.shape) - 1 # def trafo(c_): # q = tuple(c*s+o for (c,s,o) in zip(c_, s_, o_)) # return q lerp = libkrebs.PyLerp( o_, s_) # speedup of c++ to python implementation: ca x30!! #import time #t_ = time.time() ret = geometric_transform(data_src, lerp.apply, shape_dst, order=order, mode=mode, cval=cval) #print 'resample time: %f' % (time.time()-t_) return ret
def topolar(img, order=1): """ Transform img to its polar coordinate representation. order: int, default 1 Specify the spline interpolation order. High orders may be slow for large images. """ # max_radius is the length of the diagonal # from a corner to the mid-point of img. print "in to polar" max_radius = 0.5 * np.linalg.norm(img.shape) def transform(coords): # Put coord[1] in the interval, [-pi, pi] theta = 2 * np.pi * coords[1] / (img.shape[1] - 1.) # Then map it to the interval [0, max_radius]. #radius = float(img.shape[0]-coords[0]) / img.shape[0] * max_radius radius = max_radius * coords[0] / img.shape[0] i = 0.5 * img.shape[0] - radius * np.sin(theta) j = radius * np.cos(theta) + 0.5 * img.shape[1] return i, j print "beginning sklearn geometric transform" polar = geometric_transform(img, transform, order=order) print "finished geometric transform" rads = max_radius * np.linspace(0, 1, img.shape[0]) angs = np.linspace(0, 2 * np.pi, img.shape[1]) return polar, (rads, angs)
def skew(array, shift_size): h, l = array.shape def mapping(lc): l, c = lc dec = (dl * (l - h)) / h return l, c + dec dl = 50 c = geometric_transform(a, mapping, (h, l + dl), order=5, mode='nearest')
def undistort_imagearray(imarray, fit_distortion): pdb.set_trace() def undistort(coords): yp, xp = coords yd, xd = yp - fit_distortion(xp), xp return (yd, xd) return geometric_transform(imarray, undistort)
def __call__(self, inputs): distance = int(np.random.uniform(self.min_distance, self.max_distance)) inputs = inputs.resize_((28, 28)) inputs_np = inputs.numpy() dimen = np.random.randint(0, 2, 1) h, l = 28, 28 if dimen[0] == 0: def _mapping(lc): l, c = lc dec = (distance * (l - h)) / h return l, c + dec inputs_np = geometric_transform(inputs_np, mapping=_mapping, output_shape=(28, 28 + distance), order=self.order, mode='nearest') start = (28 + distance) // 2 - 14 end = (28 + distance) // 2 + 14 inputs_np_center = inputs_np[:, start:end].copy() inputs = torch.from_numpy(inputs_np_center) else: def _mapping(lc): l, c = lc dec = (distance * (c - h)) / h return l + dec, c inputs_np = geometric_transform(inputs_np, mapping=_mapping, output_shape=(28 + distance, 28), order=self.order, mode='nearest') start = (28 + distance) // 2 - 14 end = (28 + distance) // 2 + 14 inputs_np_center = inputs_np[start:end, ].copy() inputs = torch.from_numpy(inputs_np_center) return inputs.resize_((1, 28, 28))
def distort_line(im, distort=3.0, sigma=10, eps=0.03, delta=0.3): """ Distorts a line image. Run BEFORE degrade_line as a white border of 5 pixels will be added. Args: im (PIL.Image): Input image distort (float): sigma (float): eps (float): delta (float): Returns: PIL.Image in mode 'L' """ w, h = im.size # XXX: determine correct output shape from transformation matrices instead # of guesstimating. logger.debug('Pasting source image into canvas') image = Image.new('L', (int(1.5 * w), 4 * h), 255) image.paste(im, (int((image.size[0] - w) / 2), int( (image.size[1] - h) / 2))) line = pil2array(image.convert('L')) # shear in y direction with factor eps * randn(), scaling with 1 + eps * # randn() in x/y axis (all offset at d) logger.debug('Performing affine transformation') m = np.array([[1 + eps * np.random.randn(), 0.0], [eps * np.random.randn(), 1.0 + eps * np.random.randn()]]) c = np.array([w / 2.0, h / 2]) d = c - np.dot(m, c) + np.array( [np.random.randn() * delta, np.random.randn() * delta]) line = affine_transform(line, m, offset=d, order=1, mode='constant', cval=255) hs = gaussian_filter(np.random.randn(4 * h, int(1.5 * w)), sigma) ws = gaussian_filter(np.random.randn(4 * h, int(1.5 * w)), sigma) hs *= distort / np.amax(hs) ws *= distort / np.amax(ws) def _f(p): return (p[0] + hs[p[0], p[1]], p[1] + ws[p[0], p[1]]) logger.debug('Performing geometric transformation') im = array2pil(geometric_transform(line, _f, order=1, mode='nearest')) logger.debug('Cropping canvas to content box') im = im.crop(ImageOps.invert(im).getbbox()) return im
def cells_from_points(array): from scipy.ndimage.interpolation import geometric_transform def shift_func(output_coords): return (output_coords[0] - 0.5, output_coords[1] - 0.5) cells = geometric_transform(array, shift_func, output_shape=(array.shape[0] - 1, array.shape[1] - 1)) return cells
def ocropy_degrade(im, distort=1.0, dsigma=20.0, eps=0.03, delta=0.3, degradations=[(0.5, 0.0, 0.5, 0.0)]): """ Degrades and distorts a line using the same noise model used by ocropus. Args: im (PIL.Image): Input image distort (float): dsigma (float): eps (float): delta (float): degradations (list): list returning 4-tuples corresponding to the degradations argument of ocropus-linegen. Returns: PIL.Image in mode 'L' """ w, h = im.size # XXX: determine correct output shape from transformation matrices instead # of guesstimating. image = Image.new('L', (int(1.5*w), 4*h), 255) image.paste(im, (int((image.size[0] - w) / 2), int((image.size[1] - h) / 2))) a = pil2array(image.convert('L')) (sigma,ssigma,threshold,sthreshold) = degradations[np.random.choice(len(degradations))] sigma += (2*np.random.rand()-1)*ssigma threshold += (2*np.random.rand()-1)*sthreshold a = a*1.0/np.amax(a) if sigma>0.0: a = gaussian_filter(a,sigma) a += np.clip(np.random.randn(*a.shape)*0.2,-0.25,0.25) m = np.array([[1+eps*np.random.randn(),0.0],[eps*np.random.randn(),1.0+eps*np.random.randn()]]) w,h = a.shape c = np.array([w/2.0,h/2]) d = c-np.dot(m, c)+np.array([np.random.randn()*delta, np.random.randn()*delta]) a = affine_transform(a, m, offset=d, order=1, mode='constant', cval=a[0,0]) a = np.array(a>threshold,'f') [[r,c]] = find_objects(np.array(a==0,'i')) r0 = r.start r1 = r.stop c0 = c.start c1 = c.stop a = a[r0-5:r1+5,c0-5:c1+5] if distort > 0: h,w = a.shape hs = np.random.randn(h,w) ws = np.random.randn(h,w) hs = gaussian_filter(hs, dsigma) ws = gaussian_filter(ws, dsigma) hs *= distort/np.amax(hs) ws *= distort/np.amax(ws) def f(p): return (p[0]+hs[p[0],p[1]],p[1]+ws[p[0],p[1]]) a = geometric_transform(a, f, output_shape=(h,w), order=1, mode='constant', cval=np.amax(a)) im = array2pil(a).convert('L') return im
def polar(img, order=5): max_radius = 0.5*np.linalg.norm(img.shape) def transform(coords): theta = (2.0*np.pi*coords[1])/(img.shape[1] -1.) radius = (max_radius*coords[0])/img.shape[0] i = 0.5*img.shape[0] - radius*np.sin(theta) + img.shape[1] #+ 250 j = radius*np.cos(theta) + 0.5*img.shape[1] + img.shape[1] #+ 250 return i, j impolar = geometric_transform(img, transform, order=order, mode='nearest', prefilter=True) return impolar
def skew(image): """ Skew the provided image. Source: http://stackoverflow.com/a/33088550/4855984 """ h, l = image.shape dl = np.random.normal(loc=15, scale=5) # Norm = 15px, Sigma = 5px def mapping(lc): l, c = lc dec = (dl*(l-h))/h return l, c+dec return geometric_transform(image, mapping, (h, l), order=5, mode='nearest')
def topolar(img, C, R, order=1, ret_mapping=False): # Transforms an image from cartasian coordinates to polar coordinates # img: image # C: center of polar coordinates # R max radius # order: order of the spline interpolation mapping_function = get_mapping_function(C, 720, 200, 2*np.pi, R) polar = geometric_transform(img, mapping_function, output_shape=[720, 200], order=order) if ret_mapping: return polar, mapping_function return polar
def apply_affine(input_volume, affine_matrix, method="python", Slicer_path="Slicer", reference_file=''): """ Provides methods for applying an affine matrix to a 3D volume. TODO: extend this past 3D volumes. Also has a method to apply the matrix in Slicer, if Slice is available. Slicer will be much faster, but requires a special array format. TODO: Get this working for 4D Volumes. """ input_numpy = convert_input_2_numpy(input_volume) if method == 'python': def affine_calculation(output_coords): output_coords = output_coords + (0, ) return tuple( np.matmul(affine_matrix, np.array(output_coords))[:-1]) return geometric_transform(input_numpy, affine_calculation) elif method == 'slicer': save_numpy_2_nifti(input_numpy, reference_file, 'temp.nii.gz') save_affine(affine_matrix, 'temp.txt') Slicer_Command = [ Slicer_path, '--launch', 'ResampleScalarVectorDWIVolume', 'temp.nii.gz', 'temp_out.nii.gz', '-f', 'temp.txt', '-i', 'bs' ] call(' '.join(Slicer_Command), shell=True) output_array = convert_input_2_numpy('temp_out.nii.gz') os.remove('temp.nii.gz') os.remove('temp.txt') os.remove('temp_out.nii.gz') return output_array # return convert_input_2_numpy('temp_out.nii.gz') else: print 'Invalid method parameter. Returning []' return []
def transfromxy2polar(matrixxy, extentxy, extentpolar, shapepolar, ashistogram=True): ''' remaps a matrix matrixxy in kartesian coordinates x,y to a polar representation with axes r, phi. ''' from scipy.ndimage.interpolation import geometric_transform import numpy as np def polar2xy(rphi): (r, phi) = rphi x = r * np.cos(phi) y = r * np.sin(phi) return (x, y) def koord2index(q1q2, extent, shape): (q1, q2) = q1q2 return ((q1 - extent[0]) / (extent[1] - extent[0]) * shape[0], (q2 - extent[2]) / (extent[3] - extent[2]) * shape[1]) def index2koord(ij, extent, shape): (i, j) = ij return (extent[0] + i / shape[0] * (extent[1] - extent[0]), extent[2] + j / shape[1] * (extent[3] - extent[2])) def mappingxy2polar(ij, extentxy, shapexy, extentpolar, shapepolar): ''' actually maps indizes of polar matrix to indices of kartesian matrix ''' (i, j) = ij ret = polar2xy( index2koord((float(i), float(j)), extentpolar, shapepolar)) ret = koord2index(ret, extentxy, shapexy) return ret ret = geometric_transform(matrixxy, mappingxy2polar, output_shape=shapepolar, extra_arguments=(extentxy, matrixxy.shape, extentpolar, shapepolar), order=1) if ashistogram: # volumeelement is just r r = np.abs(np.linspace(extentpolar[0], extentpolar[1], ret.shape[0])) ret = (ret.T * r).T return ret
def topolar(img, order=5): max_radius = 0.5 * np.linalg.norm(img.shape) def transform(coords): theta = 2.0 * np.pi * coords[1] / (img.shape[1] - 1.) radius = max_radius * coords[0] / img.shape[0] i = 0.5 * img.shape[0] - radius * np.sin(theta) j = radius * np.cos(theta) + 0.5 * img.shape[1] return i, j polar = geometric_transform(img, transform, order=order, mode='nearest', prefilter=True) return polar
def distort_line(im, distort=3.0, sigma=10, eps=0.03, delta=0.3): """ Distorts a line image. Run BEFORE degrade_line as a white border of 5 pixels will be added. Args: im (PIL.Image): Input image distort (float): sigma (float): eps (float): delta (float): Returns: PIL.Image in mode 'L' """ w, h = im.size # XXX: determine correct output shape from transformation matrices instead # of guesstimating. logger.debug(u'Pasting source image into canvas') image = Image.new('L', (int(1.5*w), 4*h), 255) image.paste(im, (int((image.size[0] - w) / 2), int((image.size[1] - h) / 2))) line = pil2array(image.convert('L')) # shear in y direction with factor eps * randn(), scaling with 1 + eps * # randn() in x/y axis (all offset at d) logger.debug(u'Performing affine transformation') m = np.array([[1 + eps * np.random.randn(), 0.0], [eps * np.random.randn(), 1.0 + eps * np.random.randn()]]) c = np.array([w/2.0, h/2]) d = c - np.dot(m, c) + np.array([np.random.randn() * delta, np.random.randn() * delta]) line = affine_transform(line, m, offset=d, order=1, mode='constant', cval=255) hs = gaussian_filter(np.random.randn(4*h, int(1.5*w)), sigma) ws = gaussian_filter(np.random.randn(4*h, int(1.5*w)), sigma) hs *= distort/np.amax(hs) ws *= distort/np.amax(ws) def _f(p): return (p[0] + hs[p[0], p[1]], p[1] + ws[p[0], p[1]]) logger.debug(u'Performing geometric transformation') im = array2pil(geometric_transform(line, _f, order=1, mode='nearest')) logger.debug(u'Cropping canvas to content box') im = im.crop(ImageOps.invert(im).getbbox()) return im
def rdistort(image, distort=3.0, dsigma=10.0, cval=0): h, w = image.shape hs = np.random.randn(h, w) ws = np.random.randn(h, w) hs = filters.gaussian_filter(hs, dsigma) ws = filters.gaussian_filter(ws, dsigma) hs *= distort / amax(hs) ws *= distort / amax(ws) def f(p): return (p[0] + hs[p[0], p[1]], p[1] + ws[p[0], p[1]]) return interpolation.geometric_transform(image, f, output_shape=(h, w), order=1, mode='constant', cval=cval)
def fix_distortion(image, centers, tracedir=-1): '''Fit the path of the trace with a polynomial, and warp the image back to straight.''' tracedir = abs(tracedir) centers = Robust2D(centers) centers = (centers.T - centers.T[0,:]).T.combine() distortion = centers.fit_to_model(Polynomial1D(degree=2), x=centers.index) def undistort(coords): xp, yp = coords if tracedir: xp, yp = yp, xp if tracedir: return yp - distortion(xp), xp return xp, yp-distortion(xp) return geometric_transform(image, undistort)
def topolar(img, center, order=5): # max_radius = 0.5 * np.linalg.norm(img.shape) # def transform(coords): # """ # :param coords: coords in output image # :return: coords in input image # """ # theta = 2.0 * np.pi * coords[1] / (img.shape[1] - 1.) # radius = max_radius * coords[0] / img.shape[0] # i = center[0] - radius * np.sin(theta) # j = center[1] - radius * np.cos(theta) # return i, j transform2polar_p = partial(transform2polar, center=center, shape=img.shape) polar = geometric_transform(img, transform2polar_p, order=order, mode='nearest', prefilter=True) return polar
def transfromxy2polar(matrixxy, extentxy, extentpolar, shapepolar, ashistogram=True): ''' remaps a matrix matrixxy in kartesian coordinates x,y to a polar representation with axes r, phi. ''' from scipy.ndimage.interpolation import geometric_transform import numpy as np def polar2xy(rphi): (r, phi) = rphi x = r * np.cos(phi) y = r * np.sin(phi) return (x, y) def koord2index(q1q2, extent, shape): (q1, q2) = q1q2 return ((q1 - extent[0]) / (extent[1] - extent[0]) * shape[0], (q2 - extent[2]) / (extent[3] - extent[2]) * shape[1]) def index2koord(ij, extent, shape): (i, j) = ij return (extent[0] + i / shape[0] * (extent[1] - extent[0]), extent[2] + j / shape[1] * (extent[3] - extent[2])) def mappingxy2polar(ij, extentxy, shapexy, extentpolar, shapepolar): ''' actually maps indizes of polar matrix to indices of kartesian matrix ''' (i, j) = ij ret = polar2xy(index2koord((float(i), float(j)), extentpolar, shapepolar)) ret = koord2index(ret, extentxy, shapexy) return ret ret = geometric_transform(matrixxy, mappingxy2polar, output_shape=shapepolar, extra_arguments=(extentxy, matrixxy.shape, extentpolar, shapepolar), order=1) if ashistogram: # volumeelement is just r r = np.abs(np.linspace(extentpolar[0], extentpolar[1], ret.shape[0])) ret = (ret.T * r).T return ret
def topolar(img, order=3): """ Transform img to its polar coordinate representation. order: int, default 1 Specify the spline interpolation order. High orders may be slow for large images. """ # max_radius is the length of the diagonal # from a corner to the mid-point of img. max_radius = 0.5 * np.linalg.norm(img.shape) #print(img.shape) #print(max_radius) def transform(coords): #print("coords ",coords) # Put coord[1] in the interval, [-pi, pi] theta = 2 * np.pi * coords[1] / (img.shape[1] - 1.) #print("theta ", theta) # Then map it to the interval [0, max_radius]. #radius = float(img.shape[0]-coords[0]) / img.shape[0] * max_radius radius = max_radius * coords[0] / img.shape[0] #print("radius ", radius) i = 0.5 * img.shape[0] - radius * np.sin(theta) j = radius * np.cos(theta) + 0.5 * img.shape[1] #print(i,j) #print() if coords == (0, 0): print(coords) print(theta, radius) return i, j polar = geometric_transform(img, transform, order=order) print(img.shape, polar.shape) rads = max_radius * np.linspace(0, 1, img.shape[0]) angs = np.linspace(0, 2 * np.pi, img.shape[1]) return polar, (rads, angs)
def tocart(img, center, order=5): # max_radius = 0.5 * np.linalg.norm(img.shape) # def transform(coords): # """ # :param coords: coords in output image # :return: coords in input image # """ # xindex, yindex = coords # x = xindex - center[1] # y = yindex - center[0] # r = np.sqrt(x ** 2.0 + y ** 2.0) * (img.shape[1] / max_radius) # theta = np.arctan2(y, x, where=True) # theta_index = (theta + np.pi) * img.shape[1] / (2 * np.pi) # return (r, theta_index) transform2cart_p = partial(transform2cart, center=center, shape=img.shape) polar = geometric_transform(img, transform2cart_p, order=order, mode='nearest', prefilter=True) return polar
def warp_image(image, field): from scipy.ndimage.interpolation import geometric_transform #output = np.zeros_like(image) def warp_lookup(tup, strength=0.5): fv = field[tup[0], tup[1]] if len(tup) == 2: return int(tup[0] + fv[0] * strength), int(tup[1] + fv[1] * strength) elif len(tup) == 3: return int(tup[0] + fv[0] * strength), int(tup[1] + fv[1] * strength), tup[2] output = geometric_transform(image, warp_lookup, output_shape=image.shape, order=3) return output
def frame_rescaling(array, ref_xy=None, scale=1.0, imlib='vip-fft', interpolation='lanczos4', scale_y=None, scale_x=None): """ Rescale a frame by a factor wrt a reference point. The reference point is by default the center of the frame (typically the exact location of the star). However, it keeps the same dimensions. Parameters ---------- array : numpy ndarray Input frame, 2d array. ref_xy : float, optional Coordinates X,Y of the point wrt which the rescaling will be applied. By default the rescaling is done with respect to the center of the frame. scale : float Scaling factor. If > 1, it will upsample the input array equally along y and x by this factor. imlib : {'ndimage', 'opencv', 'vip-fft'}, optional Library used for image transformations. 'vip-fft' corresponds to a FFT-based rescaling algorithm implemented in VIP (``vip_hci.preproc.scale_fft``). interpolation : str, optional For 'ndimage' library: 'nearneig', bilinear', 'biquadratic', 'bicubic', 'biquartic', 'biquintic'. The 'nearneig' interpolation is the fastest and the 'biquintic' the slowest. The 'nearneig' is the worst option for interpolation of noisy astronomical images. For 'opencv' library: 'nearneig', 'bilinear', 'bicubic', 'lanczos4'. The 'nearneig' interpolation is the fastest and the 'lanczos4' the slowest and accurate. scale_y : float Scaling factor only for y axis. If provided, it takes priority on scale parameter. scale_x : float Scaling factor only for x axis. If provided, it takes priority on scale parameter. Returns ------- array_out : numpy ndarray Resulting frame. """ if array.ndim != 2: raise TypeError('Input array is not a frame or 2d array.') if scale_y is None: scale_y = scale if scale_x is None: scale_x = scale outshape = array.shape if ref_xy is None: ref_xy = frame_center(array) else: if imlib == 'vip-fft' and ref_xy != frame_center(array): msg = "'vip-fft'imlib does not yet allow for custom center to be " msg+= " provided " raise ValueError(msg) # Replace any NaN with real values before scaling mask = None nan_mask = np.isnan(array) if np.any(nan_mask): medval = np.nanmedian(array) array[nan_mask] = medval mask = np.zeros_like(array) mask[nan_mask] = 1 if imlib == 'ndimage': if interpolation == 'nearneig': order = 0 elif interpolation == 'bilinear': order = 1 elif interpolation == 'biquadratic': order = 2 elif interpolation == 'bicubic': order = 3 elif interpolation == 'biquartic' or interpolation == 'lanczos4': order = 4 elif interpolation == 'biquintic': order = 5 else: raise TypeError( 'Scipy.ndimage interpolation method not recognized') array_out = geometric_transform(array, _scale_func, order=order, output_shape=outshape, extra_keywords={'ref_xy': ref_xy, 'scaling': scale, 'scale_y': scale_y, 'scale_x': scale_x}) array_out /= scale_y * scale_x elif imlib == 'opencv': if no_opencv: msg = 'Opencv python bindings cannot be imported. Install ' msg += ' opencv or set imlib to skimage' raise RuntimeError(msg) if interpolation == 'bilinear': intp = cv2.INTER_LINEAR elif interpolation == 'bicubic': intp = cv2.INTER_CUBIC elif interpolation == 'nearneig': intp = cv2.INTER_NEAREST elif interpolation == 'lanczos4': intp = cv2.INTER_LANCZOS4 else: raise TypeError('Opencv interpolation method not recognized') M = np.array([[scale_x, 0, (1. - scale_x) * ref_xy[0]], [0, scale_y, (1. - scale_y) * ref_xy[1]]]) array_out = cv2.warpAffine(array.astype(np.float32), M, outshape, flags=intp) array_out /= scale_y * scale_x elif imlib == 'vip-fft': if scale_x != scale_y: msg='FFT scaling only supports identical factors along x and y' raise ValueError(msg) if array.shape[0] != array.shape[1]: msg='FFT scaling only supports square input arrays' raise ValueError(msg) # make array with even dimensions before FFT-scaling if array.shape[0]%2: odd=True array_even = np.zeros([array.shape[0]+1,array.shape[1]+1]) array_even[1:,1:] = array array = array_even else: odd = False if mask is not None: if odd: mask_even = np.zeros([mask.shape[0]+1,mask.shape[1]+1]) mask_even[1:,1:] = mask mask = mask_even mask = scale_fft(mask, scale_x, ori_dim=True) if odd: mask_odd = np.zeros([mask.shape[0]-1,mask.shape[1]-1]) mask_odd = mask[1:,1:] mask = mask_odd array_out = scale_fft(array, scale_x, ori_dim=True) if odd: array = np.zeros([array_out.shape[0]-1,array_out.shape[1]-1]) array = array_out[1:,1:] array_out = array else: raise ValueError('Image transformation library not recognized') # Place back NaN values in scaled array if mask is not None: array_out[mask >= 0.5] = np.nan return array_out
def frame_rescaling(array, ref_y=None, ref_x=None, scale=1.0, method='geometric_transform'): """ Function to rescale a frame by a factor 'scale', wrt a reference point ref_pt which by default is the center of the frame (typically the exact location of the star). However, it keeps the same dimensions. It uses spline interpolation of order 3 to find the new values in the output array. Parameters ---------- array : array_like Input frame, 2d array. ref_y, ref_x : float, optional Coordinates X,Y of the point with respect to which the rotation will be performed. By default the rotation is done with respect to the center of the frame; central pixel if frame has odd size. scale : float Scaling factor. If > 1, it will upsample the input array. method: string, {'geometric_transform','cv2.warp_affine'}, optional String determining which library to apply to rescale. Both options use a spline of order 3 for interpolation. Opencv is a few order of magnitudes faster than ndimage. Returns ------- array_out : array_like Resulting frame. """ def _scale_func(output_coords,ref_y=0,ref_x=0, scaling=1.0): """ For each coordinate point in a new scaled image (output_coords), coordinates in the image before the scaling are returned. This scaling function is used within geometric_transform (in frame_rescaling), which, for each point in the output image, will compute the (spline) interpolated value at the corresponding frame coordinates before the scaling. """ return (ref_y+((output_coords[0]-ref_y)/scaling), ref_x+((output_coords[1]-ref_x)/scaling)) array_out = np.zeros_like(array) if not ref_y and not ref_x: ref_y, ref_x = frame_center(array) if method == 'geometric_transform': geometric_transform(array, _scale_func, output_shape=array.shape, output = array_out, extra_keywords={'ref_y':ref_y,'ref_x':ref_x, 'scaling':scale}) elif method == 'cv2.warp_affine': M = np.array([[scale,0,(1.-scale)*ref_x],[0,scale,(1.-scale)*ref_y]]) array_out = cv2.warpAffine(array.astype(np.float32), M, (array.shape[1], array.shape[0]), flags=cv2.INTER_LINEAR) else: msg="Pick a valid method: 'geometric_transform' or 'cv2.warp_affine'" raise ValueError(msg) return array_out
def _frame_rescaling(array, ref_xy=None, scale=1.0, imlib='opencv', interpolation='lanczos4', scale_y=None, scale_x=None): """ Rescale a frame by a factor wrt a reference point. The reference point is by default the center of the frame (typically the exact location of the star). However, it keeps the same dimensions. Parameters ---------- array : numpy ndarray Input frame, 2d array. ref_xy : float, optional Coordinates X,Y of the point wrt which the rescaling will be applied. By default the rescaling is done with respect to the center of the frame. scale : float Scaling factor. If > 1, it will upsample the input array equally along y and x by this factor. scale_y : float Scaling factor only for y axis. If provided, it takes priority on scale parameter. scale_x : float Scaling factor only for x axis. If provided, it takes priority on scale parameter. Returns ------- array_out : numpy ndarray Resulting frame. """ if array.ndim != 2: raise TypeError('Input array is not a frame or 2d array.') if scale_y is None: scale_y = scale if scale_x is None: scale_x = scale outshape = array.shape if ref_xy is None: ref_xy = frame_center(array) if imlib == 'ndimage': if interpolation == 'nearneig': order = 0 elif interpolation == 'bilinear': order = 1 elif interpolation == 'biquadratic': order = 2 elif interpolation == 'bicubic': order = 3 elif interpolation == 'biquartic' or interpolation == 'lanczos4': order = 4 elif interpolation == 'biquintic': order = 5 else: raise TypeError( 'Scipy.ndimage interpolation method not recognized') array_out = geometric_transform(array, _scale_func, order=order, output_shape=outshape, extra_keywords={ 'ref_xy': ref_xy, 'scaling': scale, 'scale_y': scale_y, 'scale_x': scale_x }) elif imlib == 'opencv': if no_opencv: msg = 'Opencv python bindings cannot be imported. Install ' msg += ' opencv or set imlib to skimage' raise RuntimeError(msg) if interpolation == 'bilinear': intp = cv2.INTER_LINEAR elif interpolation == 'bicubic': intp = cv2.INTER_CUBIC elif interpolation == 'nearneig': intp = cv2.INTER_NEAREST elif interpolation == 'lanczos4': intp = cv2.INTER_LANCZOS4 else: raise TypeError('Opencv interpolation method not recognized') M = np.array([[scale_x, 0, (1. - scale_x) * ref_xy[0]], [0, scale_y, (1. - scale_y) * ref_xy[1]]]) array_out = cv2.warpAffine(array.astype(np.float32), M, outshape, flags=intp) else: raise ValueError('Image transformation library not recognized') array_out /= scale_y * scale_x return array_out
return ((q1 - extent[0]) / (extent[1] - extent[0]) * shape[0], (q2 - extent[2]) / (extent[3] - extent[2]) * shape[1]) def index2koord((i, j), extent, shape): return (extent[0] + i / shape[0] * (extent[1] - extent[0]), extent[2] + j / shape[1] * (extent[3] - extent[2])) def mappingxy2polar((i, j), extentxy, shapexy, extentpolar, shapepolar): ''' actually maps indizes of polar matrix to indices of kartesian matrix ''' ret = polar2xy(index2koord((float(i), float(j)), extentpolar, shapepolar)) ret = koord2index(ret, extentxy, shapexy) return ret ret = geometric_transform(matrixxy, mappingxy2polar, output_shape=shapepolar, extra_arguments=(extentxy, matrixxy.shape, extentpolar, shapepolar), order=1) if ashistogram: # volumeelement is just r r = np.abs(np.linspace(extentpolar[0], extentpolar[1], ret.shape[0])) ret = (ret.T * r).T return ret
def cells_from_points(array): from scipy.ndimage.interpolation import geometric_transform def shift_func(output_coords): return (output_coords[0] - 0.5, output_coords[1] - 0.5) cells = geometric_transform(array, shift_func, output_shape=(array.shape[0]-1,array.shape[1]-1)) return cells
def _frame_rescaling(array, ref_xy=None, scale=1.0, imlib='opencv', interpolation='lanczos4', scale_y=None, scale_x=None): """ Rescale a frame by a factor wrt a reference point. The reference point is by default the center of the frame (typically the exact location of the star). However, it keeps the same dimensions. Parameters ---------- array : numpy ndarray Input frame, 2d array. ref_xy : float, optional Coordinates X,Y of the point wrt which the rescaling will be applied. By default the rescaling is done with respect to the center of the frame. scale : float Scaling factor. If > 1, it will upsample the input array equally along y and x by this factor. scale_y : float Scaling factor only for y axis. If provided, it takes priority on scale parameter. scale_x : float Scaling factor only for x axis. If provided, it takes priority on scale parameter. Returns ------- array_out : numpy ndarray Resulting frame. """ if array.ndim != 2: raise TypeError('Input array is not a frame or 2d array.') if scale_y is None: scale_y = scale if scale_x is None: scale_x = scale outshape = array.shape if ref_xy is None: ref_xy = frame_center(array) if imlib == 'ndimage': if interpolation == 'nearneig': order = 0 elif interpolation == 'bilinear': order = 1 elif interpolation == 'bicuadratic': order = 2 elif interpolation == 'bicubic': order = 3 elif interpolation == 'biquartic': order = 4 elif interpolation == 'biquintic': order = 5 else: raise TypeError( 'Scipy.ndimage interpolation method not recognized') array_out = geometric_transform(array, _scale_func, order=order, output_shape=outshape, extra_keywords={'ref_xy': ref_xy, 'scaling': scale, 'scale_y': scale_y, 'scale_x': scale_x}) elif imlib == 'opencv': if no_opencv: msg = 'Opencv python bindings cannot be imported. Install ' msg += ' opencv or set imlib to skimage' raise RuntimeError(msg) if interpolation == 'bilinear': intp = cv2.INTER_LINEAR elif interpolation == 'bicubic': intp = cv2.INTER_CUBIC elif interpolation == 'nearneig': intp = cv2.INTER_NEAREST elif interpolation == 'lanczos4': intp = cv2.INTER_LANCZOS4 else: raise TypeError('Opencv interpolation method not recognized') M = np.array([[scale_x, 0, (1. - scale_x) * ref_xy[0]], [0, scale_y, (1. - scale_y) * ref_xy[1]]]) array_out = cv2.warpAffine(array.astype(np.float32), M, outshape, flags=intp) else: raise ValueError('Image transformation library not recognized') array_out /= scale_y * scale_x return array_out
def frame_rescaling(array, ref_y=None, ref_x=None, scale=1.0, method='geometric_transform', scale_y=None, scale_x=None): """ Function to rescale a frame by a factor 'scale', wrt a reference point ref_pt which by default is the center of the frame (typically the exact location of the star). However, it keeps the same dimensions. It uses spline interpolation of order 3 to find the new values in the output array. Parameters ---------- array : array_like Input frame, 2d array. ref_y, ref_x : float, optional Coordinates X,Y of the point with respect to which the rotation will be performed. By default the rotation is done with respect to the center of the frame; central pixel if frame has odd size. scale : float Scaling factor. If > 1, it will upsample the input array equally along y and x by this factor. method: string, {'geometric_transform','cv2.warp_affine'}, optional String determining which library to apply to rescale. Both options use a spline of order 3 for interpolation. Opencv is a few order of magnitudes faster than ndimage. scale_y : float Scaling factor only for y axis. If provided, it takes priority on scale parameter. scale_x : float Scaling factor only for x axis. If provided, it takes priority on scale parameter. Returns ------- array_out : array_like Resulting frame. """ def _scale_func(output_coords, ref_y=0, ref_x=0, scaling=1.0, scaling_y=None, scaling_x=None): """ For each coordinate point in a new scaled image (output_coords), coordinates in the image before the scaling are returned. This scaling function is used within geometric_transform (in frame_rescaling), which, for each point in the output image, will compute the (spline) interpolated value at the corresponding frame coordinates before the scaling. """ if scaling_y is None: scaling_y = scaling if scaling_x is None: scaling_x = scaling return (ref_y + ((output_coords[0] - ref_y) / scaling_y), ref_x + ((output_coords[1] - ref_x) / scaling_x)) array_out = np.zeros_like(array) if not ref_y and not ref_x: ref_y, ref_x = frame_center(array) if method == 'geometric_transform': geometric_transform(array, _scale_func, output_shape=array.shape, output=array_out, extra_keywords={ 'ref_y': ref_y, 'ref_x': ref_x, 'scaling': scale, 'scaling_y': scale_y, 'scaling_x': scale_x }) elif method == 'cv2.warp_affine': if scale_y is None: scale_y = scale if scale_x is None: scale_x = scale M = np.array([[scale_x, 0, (1. - scale_x) * ref_x], [0, scale_y, (1. - scale_y) * ref_y]]) array_out = cv2.warpAffine(array.astype(np.float32), M, (array.shape[1], array.shape[0]), flags=cv2.INTER_CUBIC) else: msg = "Pick a valid method: 'geometric_transform' or 'cv2.warp_affine'" raise ValueError(msg) return array_out
def translate(img, x, y, order=1): def transform(coords): return coords[0] - x, coords[1] - y return geometric_transform(img, transform, order=order)
def ocropy_degrade(im, distort=1.0, dsigma=20.0, eps=0.03, delta=0.3, degradations=((0.5, 0.0, 0.5, 0.0), )): """ Degrades and distorts a line using the same noise model used by ocropus. Args: im (PIL.Image): Input image distort (float): dsigma (float): eps (float): delta (float): degradations (list): list returning 4-tuples corresponding to the degradations argument of ocropus-linegen. Returns: PIL.Image in mode 'L' """ w, h = im.size # XXX: determine correct output shape from transformation matrices instead # of guesstimating. logger.debug('Pasting source image into canvas') image = Image.new('L', (int(1.5 * w), 4 * h), 255) image.paste(im, (int((image.size[0] - w) / 2), int( (image.size[1] - h) / 2))) a = pil2array(image.convert('L')) logger.debug('Selecting degradations') (sigma, ssigma, threshold, sthreshold) = degradations[np.random.choice(len(degradations))] sigma += (2 * np.random.rand() - 1) * ssigma threshold += (2 * np.random.rand() - 1) * sthreshold a = a * 1.0 / np.amax(a) if sigma > 0.0: logger.debug('Apply Gaussian filter') a = gaussian_filter(a, sigma) logger.debug('Adding noise') a += np.clip(np.random.randn(*a.shape) * 0.2, -0.25, 0.25) logger.debug('Perform affine transformation and resize') m = np.array([[1 + eps * np.random.randn(), 0.0], [eps * np.random.randn(), 1.0 + eps * np.random.randn()]]) w, h = a.shape c = np.array([w / 2.0, h / 2]) d = c - np.dot(m, c) + np.array( [np.random.randn() * delta, np.random.randn() * delta]) a = affine_transform(a, m, offset=d, order=1, mode='constant', cval=a[0, 0]) a = np.array(a > threshold, 'f') [[r, c]] = find_objects(np.array(a == 0, 'i')) r0 = r.start r1 = r.stop c0 = c.start c1 = c.stop a = a[r0 - 5:r1 + 5, c0 - 5:c1 + 5] if distort > 0: logger.debug('Perform geometric transformation') h, w = a.shape hs = np.random.randn(h, w) ws = np.random.randn(h, w) hs = gaussian_filter(hs, dsigma) ws = gaussian_filter(ws, dsigma) hs *= distort / np.amax(hs) ws *= distort / np.amax(ws) def _f(p): return (p[0] + hs[p[0], p[1]], p[1] + ws[p[0], p[1]]) a = geometric_transform(a, _f, output_shape=(h, w), order=1, mode='constant', cval=np.amax(a)) im = array2pil(a).convert('L') return im
def frame_rescaling(array, ref_y=None, ref_x=None, scale=1.0, imlib='opencv', scale_y=None, scale_x=None): """ Function to rescale a frame by a factor 'scale', wrt a reference point ref_pt which by default is the center of the frame (typically the exact location of the star). However, it keeps the same dimensions. It uses spline interpolation of order 3 to find the new values in the output array. Parameters ---------- array : array_like Input frame, 2d array. ref_y, ref_x : float, optional Coordinates X,Y of the point with respect to which the rotation will be performed. By default the rescaling is done with respect to the center of the frame; central pixel if frame has odd size. scale : float Scaling factor. If > 1, it will upsample the input array equally along y and x by this factor. imlib: string, {'ndimage','opencv'}, optional String determining which library to apply to rescale. Both options use a spline of order 3 for interpolation. Opencv is a few order of magnitudes faster than ndimage. scale_y : float Scaling factor only for y axis. If provided, it takes priority on scale parameter. scale_x : float Scaling factor only for x axis. If provided, it takes priority on scale parameter. Returns ------- array_out : array_like Resulting frame. """ def _scale_func(output_coords, ref_y=0, ref_x=0, scaling=1.0, scaling_y=None, scaling_x=None): """ For each coordinate point in a new scaled image (output_coords), coordinates in the image before the scaling are returned. This scaling function is used within geometric_transform (in frame_rescaling), which, for each point in the output image, will compute the (spline) interpolated value at the corresponding frame coordinates before the scaling. """ if scaling_y is None: scaling_y = scaling if scaling_x is None: scaling_x = scaling return (ref_y + ((output_coords[0] - ref_y) / scaling_y), ref_x + ((output_coords[1] - ref_x) / scaling_x)) #--------------------------------------------------------------------------- if not array.ndim == 2: raise TypeError('Input array is not a frame or 2d array.') if not ref_y and not ref_x: ref_y, ref_x = frame_center(array) if imlib not in ['ndimage', 'opencv']: raise ValueError('Imlib not recognized, try opencv or ndimage') if imlib == 'ndimage' or no_opencv: outshap = array.shape array_out = geometric_transform(array, _scale_func, output_shape=outshap, extra_keywords={ 'ref_y': ref_y, 'ref_x': ref_x, 'scaling': scale, 'scaling_y': scale_y, 'scaling_x': scale_x }) else: if scale_y is None: scale_y = scale if scale_x is None: scale_x = scale M = np.array([[scale_x, 0, (1. - scale_x) * ref_x], [0, scale_y, (1. - scale_y) * ref_y]]) array_out = cv2.warpAffine(array.astype(np.float32), M, (array.shape[1], array.shape[0]), flags=cv2.INTER_CUBIC) # TODO: For conservation of flux (e.g. in aperture 1xFWHM), what to do when # there is a different scaling factor in x and y? if scale_y == scale_x: array_out /= scale**2 return array_out