From a2993241663b04aa9eb750f10e257eb0ba10b5dc Mon Sep 17 00:00:00 2001 From: iperov Date: Thu, 12 Aug 2021 14:28:36 +0400 Subject: [PATCH] _ --- core/imagelib/warp.py | 109 +++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 70 deletions(-) diff --git a/core/imagelib/warp.py b/core/imagelib/warp.py index 385d8f7..fe07a0a 100644 --- a/core/imagelib/warp.py +++ b/core/imagelib/warp.py @@ -3,97 +3,66 @@ import numpy.linalg as npla import cv2 from core import randomex +def mls_rigid_deformation(vy, vx, src_pts, dst_pts, alpha=1.0, eps=1e-8): + dst_pts = dst_pts[..., ::-1].astype(np.int16) + src_pts = src_pts[..., ::-1].astype(np.int16) -def mls_rigid_deformation(vy, vx, p, q, alpha=1.0, eps=1e-8): - """ Rigid deformation - - Parameters - ---------- - vx, vy: ndarray - coordinate grid, generated by np.meshgrid(gridX, gridY) - p: ndarray - an array with size [n, 2], original control points - q: ndarray - an array with size [n, 2], final control points - alpha: float - parameter used by weights - eps: float - epsilon - - Return - ------ - A deformed image. - """ - # Change (x, y) to (row, col) - q = np.ascontiguousarray(q[:, [1, 0]].astype(np.int16)) - p = np.ascontiguousarray(p[:, [1, 0]].astype(np.int16)) + src_pts, dst_pts = dst_pts, src_pts - # Exchange p and q and hence we transform destination pixels to the corresponding source pixels. - p, q = q, p + grow = vx.shape[0] + gcol = vx.shape[1] + ctrls = src_pts.shape[0] - grow = vx.shape[0] # grid rows - gcol = vx.shape[1] # grid cols - ctrls = p.shape[0] # control points + reshaped_p = src_pts.reshape(ctrls, 2, 1, 1) + reshaped_v = np.vstack((vx.reshape(1, grow, gcol), vy.reshape(1, grow, gcol))) - # Compute - reshaped_p = p.reshape(ctrls, 2, 1, 1) # [ctrls, 2, 1, 1] - reshaped_v = np.vstack((vx.reshape(1, grow, gcol), vy.reshape(1, grow, gcol))) # [2, grow, gcol] - - w = 1.0 / (np.sum((reshaped_p - reshaped_v).astype(np.float32) ** 2, axis=1) + eps) ** alpha # [ctrls, grow, gcol] - w /= np.sum(w, axis=0, keepdims=True) # [ctrls, grow, gcol] + w = 1.0 / (np.sum((reshaped_p - reshaped_v).astype(np.float32) ** 2, axis=1) + eps) ** alpha + w /= np.sum(w, axis=0, keepdims=True) pstar = np.zeros((2, grow, gcol), np.float32) for i in range(ctrls): - pstar += w[i] * reshaped_p[i] # [2, grow, gcol] + pstar += w[i] * reshaped_p[i] - vpstar = reshaped_v - pstar # [2, grow, gcol] - reshaped_vpstar = vpstar.reshape(2, 1, grow, gcol) # [2, 1, grow, gcol] - neg_vpstar_verti = vpstar[[1, 0],...] # [2, grow, gcol] - neg_vpstar_verti[1,...] = -neg_vpstar_verti[1,...] - reshaped_neg_vpstar_verti = neg_vpstar_verti.reshape(2, 1, grow, gcol) # [2, 1, grow, gcol] - mul_right = np.concatenate((reshaped_vpstar, reshaped_neg_vpstar_verti), axis=1) # [2, 2, grow, gcol] - reshaped_mul_right = mul_right.reshape(2, 2, grow, gcol) # [2, 2, grow, gcol] + vpstar = reshaped_v - pstar - # Calculate q - reshaped_q = q.reshape((ctrls, 2, 1, 1)) # [ctrls, 2, 1, 1] + reshaped_mul_right = np.concatenate((vpstar[:,None,...], + np.concatenate((vpstar[1:2,None,...],-vpstar[0:1,None,...]), 0) + ), axis=1).transpose(2, 3, 0, 1) + + reshaped_q = dst_pts.reshape((ctrls, 2, 1, 1)) + qstar = np.zeros((2, grow, gcol), np.float32) for i in range(ctrls): - qstar += w[i] * reshaped_q[i] # [2, grow, gcol] - + qstar += w[i] * reshaped_q[i] + temp = np.zeros((grow, gcol, 2), np.float32) for i in range(ctrls): - phat = reshaped_p[i] - pstar # [2, grow, gcol] - reshaped_phat = phat.reshape(1, 2, grow, gcol) # [1, 2, grow, gcol] - reshaped_w = w[i].reshape(1, 1, grow, gcol) # [1, 1, grow, gcol] - neg_phat_verti = phat[[1, 0]] # [2, grow, gcol] - neg_phat_verti[1] = -neg_phat_verti[1] - reshaped_neg_phat_verti = neg_phat_verti.reshape(1, 2, grow, gcol) # [1, 2, grow, gcol] - mul_left = np.concatenate((reshaped_phat, reshaped_neg_phat_verti), axis=0) # [2, 2, grow, gcol] - - A = np.matmul((reshaped_w * mul_left).transpose(2, 3, 0, 1), - reshaped_mul_right.transpose(2, 3, 0, 1)) # [grow, gcol, 2, 2] + phat = reshaped_p[i] - pstar + qhat = reshaped_q[i] - qstar - qhat = reshaped_q[i] - qstar # [2, grow, gcol] - reshaped_qhat = qhat.reshape(1, 2, grow, gcol).transpose(2, 3, 0, 1) # [grow, gcol, 1, 2] + temp += np.matmul(qhat.reshape(1, 2, grow, gcol).transpose(2, 3, 0, 1), + + np.matmul( ( w[None, i:i+1,...] * + np.concatenate((phat.reshape(1, 2, grow, gcol), + np.concatenate( (phat[None,1:2], -phat[None,0:1]), 1 )), 0) + ).transpose(2, 3, 0, 1), reshaped_mul_right + ) + ).reshape(grow, gcol, 2) - # Get final image transfomer -- 3-D array - temp += np.matmul(reshaped_qhat, A).reshape(grow, gcol, 2) # [grow, gcol, 2] + temp = temp.transpose(2, 0, 1) - temp = temp.transpose(2, 0, 1) # [2, grow, gcol] - - normed_temp = np.linalg.norm(temp, axis=0, keepdims=True) # [1, grow, gcol] - normed_vpstar = np.linalg.norm(vpstar, axis=0, keepdims=True) # [1, grow, gcol] + normed_temp = np.linalg.norm(temp, axis=0, keepdims=True) + normed_vpstar = np.linalg.norm(vpstar, axis=0, keepdims=True) nan_mask = normed_temp[0]==0 - - transformers = np.true_divide(temp, normed_temp, out=np.zeros_like(temp), where= ~nan_mask) * normed_vpstar + qstar - # fix nan values + + transformers = np.true_divide(temp, normed_temp, out=np.zeros_like(temp), where= ~nan_mask) * normed_vpstar + qstar nan_mask_flat = np.flatnonzero(nan_mask) nan_mask_anti_flat = np.flatnonzero(~nan_mask) + transformers[0][nan_mask] = np.interp(nan_mask_flat, nan_mask_anti_flat, transformers[0][~nan_mask]) transformers[1][nan_mask] = np.interp(nan_mask_flat, nan_mask_anti_flat, transformers[1][~nan_mask]) - - return transformers - + + return transformers def gen_pts(W, H, rnd_state=None):