アフィン変換記事
わかりやすい。scipy の matrix は output --> input としているので、T @ vec
のアフィン変換をする場合は、matrix=mat_inv(T)
と逆行列を指定する必要がある。
from scipy.ndimage import affine_transform from numpy.linalg import inv as mat_inv def center_transform(affine, input_shape): hi, wi = float(input_shape[0]), float(input_shape[1]) ho, wo = float(img_shape[0]), float(img_shape[1]) top, left, bottom, right = 0, 0, hi, wi if wi/hi/anisotropy < wo/ho: # input image too narrow, extend width w = hi*wo/ho*anisotropy left = (wi-w)/2 right = left + w else: # input image too wide, extend height h = wi*ho/wo/anisotropy top = (hi-h)/2 bottom = top + h center_matrix = np.array([[1, 0, -ho/2], [0, 1, -wo/2], [0, 0, 1]]) scale_matrix = np.array([[(bottom - top)/ho, 0, 0], [0, (right - left)/wo, 0], [0, 0, 1]]) decenter_matrix = np.array([[1, 0, hi/2], [0, 1, wi/2], [0, 0, 1]]) return np.dot(np.dot(decenter_matrix, scale_matrix), np.dot(affine, center_matrix)) def transform_img(x, affine): matrix = affine[:2,:2] offset = affine[:2,2] x = np.moveaxis(x, -1, 0) channels = [affine_transform(channel, matrix, offset, output_shape=img_shape[:-1], order=1, mode='constant', cval=np.average(channel)) for channel in x] return np.moveaxis(np.stack(channels, axis=0), 0, -1) val_a = np.zeros((len(val),)+img_shape,dtype=K.floatx()) # Preprocess validation images val_b = np.zeros((len(val),4),dtype=K.floatx()) # Preprocess bounding boxes for i,(p,coords) in enumerate(tqdm_notebook(val)): img,trans = read_for_validation(p) coords = coord_transform(coords, mat_inv(trans)) x0,y0,x1,y1 = bounding_rectangle(coords) val_a[i,:,:,:] = img val_b[i,0] = x0 val_b[i,1] = y0 val_b[i,2] = x1 val_b[i,3] = y1