ppf_icp.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import cv2 as cv
  2. import numpy as np
  3. def rotation(theta):
  4. tx, ty, tz = theta
  5. Rx = np.array([[1, 0, 0], [0, np.cos(tx), -np.sin(tx)], [0, np.sin(tx), np.cos(tx)]])
  6. Ry = np.array([[np.cos(ty), 0, -np.sin(ty)], [0, 1, 0], [np.sin(ty), 0, np.cos(ty)]])
  7. Rz = np.array([[np.cos(tz), -np.sin(tz), 0], [np.sin(tz), np.cos(tz), 0], [0, 0, 1]])
  8. return np.dot(Rx, np.dot(Ry, Rz))
  9. width = 20
  10. height = 10
  11. max_deg = np.pi / 12
  12. cloud, rotated_cloud = [None]*3, [None]*3
  13. retval, residual, pose = [None]*3, [None]*3, [None]*3
  14. noise = np.random.normal(0.0, 0.1, height * width * 3).reshape((-1, 3))
  15. noise2 = np.random.normal(0.0, 1.0, height * width)
  16. x, y = np.meshgrid(
  17. range(-width//2, width//2),
  18. range(-height//2, height//2),
  19. sparse=False, indexing='xy'
  20. )
  21. z = np.zeros((height, width))
  22. cloud[0] = np.dstack((x, y, z)).reshape((-1, 3)).astype(np.float32)
  23. cloud[1] = noise.astype(np.float32) + cloud[0]
  24. cloud[2] = cloud[1]
  25. cloud[2][:, 2] += noise2.astype(np.float32)
  26. R = rotation([
  27. 0, #np.random.uniform(-max_deg, max_deg),
  28. np.random.uniform(-max_deg, max_deg),
  29. 0, #np.random.uniform(-max_deg, max_deg)
  30. ])
  31. t = np.zeros((3, 1))
  32. Rt = np.vstack((
  33. np.hstack((R, t)),
  34. np.array([0, 0, 0, 1])
  35. )).astype(np.float32)
  36. icp = cv.ppf_match_3d_ICP(100)
  37. I = np.eye(4)
  38. print("Unaligned error:\t%.6f" % np.linalg.norm(I - Rt))
  39. for i in range(3):
  40. rotated_cloud[i] = np.matmul(Rt[0:3,0:3], cloud[i].T).T + Rt[:3,3].T
  41. retval[i], residual[i], pose[i] = icp.registerModelToScene(rotated_cloud[i], cloud[i])
  42. print("ICP error:\t\t%.6f" % np.linalg.norm(I - np.matmul(pose[0], Rt)))