align_and_crop.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import cv2
  2. import numpy as np
  3. def get_similarity_transform(src_pts, dst_pts):
  4. """Get similarity transform matrix from src_pts to dst_pts
  5. Args:
  6. src_pts: Kx2 np.array
  7. source points matrix, each row is a pair of coordinates (x, y)
  8. dst_pts: Kx2 np.array
  9. destination points matrix, each row is a pair of coordinates (x, y)
  10. Returns:
  11. xform_matrix: 3x3 np.array
  12. transform matrix from src_pts to dst_pts
  13. """
  14. src_pts = np.asarray(src_pts)
  15. dst_pts = np.asarray(dst_pts)
  16. assert src_pts.shape == dst_pts.shape
  17. assert (src_pts.ndim == 2) and (src_pts.shape[-1] == 2)
  18. npts = src_pts.shape[0]
  19. A = np.empty((npts * 2, 4))
  20. b = np.empty((npts * 2,))
  21. for k in range(npts):
  22. A[2 * k + 0] = [src_pts[k, 0], -src_pts[k, 1], 1, 0]
  23. A[2 * k + 1] = [src_pts[k, 1], src_pts[k, 0], 0, 1]
  24. b[2 * k + 0] = dst_pts[k, 0]
  25. b[2 * k + 1] = dst_pts[k, 1]
  26. x = np.linalg.lstsq(A, b, rcond=-1)[0]
  27. xform_matrix = np.empty((3, 3))
  28. xform_matrix[0] = [x[0], -x[1], x[2]]
  29. xform_matrix[1] = [x[1], x[0], x[3]]
  30. xform_matrix[2] = [0, 0, 1]
  31. return xform_matrix
  32. def align_and_crop(image, landmarks, std_landmarks, align_size,
  33. border_value=0, return_transform_matrix=False):
  34. landmarks = np.asarray(landmarks)
  35. std_landmarks = np.asarray(std_landmarks)
  36. xform_matrix = get_similarity_transform(landmarks, std_landmarks)
  37. landmarks_ex = np.pad(landmarks, ((0,0),(0,1)), mode='constant', constant_values=1)
  38. dst_landmarks = np.dot(landmarks_ex, xform_matrix[:2,:].T)
  39. dst_image = cv2.warpAffine(image, xform_matrix[:2,:], dsize=align_size,
  40. borderValue=border_value)
  41. if return_transform_matrix:
  42. return dst_image, dst_landmarks, xform_matrix
  43. else:
  44. return dst_image, dst_landmarks