get_screen_params.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import cv2
  2. import numpy as np
  3. import glob
  4. from scipy.io import savemat
  5. import matplotlib.pyplot as plt
  6. # 读取文件夹中的所有棋盘格图像
  7. # images = glob.glob('calibration/screen_calibration/*.bmp')
  8. def calibrate_screen(screen_img_path, cam_mtx, cam_dist, chessboard_size, square_size, debug=False):
  9. # Prepare object points for chessboard corners in world coordinates
  10. objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32)
  11. objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
  12. objp *= square_size
  13. # import pdb; pdb.set_trace()
  14. objpoints = [] # 三维点
  15. imgpoints = [] # 二维点
  16. for img_path in screen_img_path:
  17. image_data = np.fromfile(img_path, dtype=np.uint8)
  18. img = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
  19. # import pdb; pdb.set_trace()
  20. dst = cv2.undistort(img, cam_mtx, cam_dist, None, None)
  21. gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
  22. # alpha = 3 # 对比度保持不变
  23. # beta = 0 # 增加亮度
  24. # bright_image = cv2.convertScaleAbs(gray, alpha=alpha, beta=beta)
  25. # cv2.namedWindow('bright_image', 0)
  26. # cv2.imshow('bright_image', bright_image)
  27. # cv2.namedWindow('gray', 0)
  28. # cv2.imshow('gray', gray)
  29. # cv2.waitKey(0)
  30. # cv2.destroyAllWindows()
  31. ret, corners = cv2.findChessboardCorners(gray, chessboard_size, flags=cv2.CALIB_CB_FAST_CHECK)
  32. if ret:
  33. print('screen img_path = ',img_path)
  34. objpoints.append(objp)
  35. criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
  36. corners_refined = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
  37. imgpoints.append(corners_refined)
  38. if debug:
  39. img = cv2.drawChessboardCorners(img, chessboard_size, corners, ret)
  40. # 在角点图像上标记坐标原点(第一个角点)
  41. origin = tuple(corners[0].ravel().astype(int))
  42. cv2.putText(img, '(0,0)', origin, cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
  43. # 添加 x 轴箭头 (右方向)
  44. end_x = tuple(corners[1].ravel().astype(int)) # 选择横向的下一个角点
  45. cv2.arrowedLine(img, origin, end_x, (255, 255, 255), 2, tipLength=0.2)
  46. cv2.putText(img, 'X', (end_x[0] + 10, end_x[1]), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
  47. # 添加 y 轴箭头 (下方向)
  48. end_y = tuple(corners[chessboard_size[0]].ravel().astype(int)) # 选择纵向的下一个角点
  49. cv2.arrowedLine(img, origin, end_y, (255, 255, 255), 2, tipLength=0.2)
  50. cv2.putText(img, 'Y', (end_y[0], end_y[1] + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
  51. cv2.namedWindow('screen', 0)
  52. cv2.imshow('screen', img)
  53. cv2.waitKey(0)
  54. cv2.destroyAllWindows()
  55. # import pdb; pdb.set_trace()
  56. objpoints = np.array(objpoints)
  57. imgpoints = np.array(imgpoints)
  58. # import pdb; pdb.set_trace()
  59. # if debug:
  60. # # 使用两幅子图绘制 objp 和 corners 的点
  61. # fig, ax = plt.subplots(1, 2, figsize=(12, 6))
  62. # # 第一个子图:objp 点
  63. # ax[0].scatter(objpoints[-1, :, 0], objpoints[-1, :, 1], color='blue', label='objp (Object Points)')
  64. # for i in range(len(objpoints[0])):
  65. # ax[0].text(objpoints[-1, i, 0], objpoints[-1, i, 1], f'{i}', color='blue', fontsize=12)
  66. # ax[0].set_title('Object Points (objp)')
  67. # ax[0].set_xlabel('X Axis')
  68. # ax[0].set_ylabel('Y Axis')
  69. # ax[0].grid(True)
  70. # ax[0].axis('equal')
  71. # # 第二个子图:corners 点
  72. # ax[1].scatter(imgpoints[-1, :, 0, 0], imgpoints[-1, :, 0, 1], color='red', label='corners (Image Points)')
  73. # for i in range(len(imgpoints[0])):
  74. # ax[1].text(imgpoints[-1, i, 0, 0], imgpoints[-1, i, 0, 1], f'{i}', color='red', fontsize=12)
  75. # ax[1].set_title('Screen Image Points (corners)')
  76. # ax[1].set_xlabel('X Axis')
  77. # ax[1].set_ylabel('Y Axis')
  78. # ax[1].grid(True)
  79. # ax[1].axis('equal')
  80. # # 调整布局并显示图像
  81. # plt.tight_layout()
  82. # plt.show()
  83. #print("camera Calibration mtx:", cam_mtx)
  84. #print("Screen Calibration dist:", cam_dist)
  85. ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], cam_mtx, cam_dist)
  86. # 获得最后一张图片的旋转矩阵和平移向量
  87. # import pdb; pdb.set_trace()
  88. R = cv2.Rodrigues(rvecs[-1])[0] # 转换为旋转矩阵
  89. # R, _ = cv2.Rodrigues(np.array([[0.024044506712974],[0.002032279577832],[-3.138030042895759]]))
  90. T = tvecs[-1]
  91. # print("*"*100)
  92. # print("Screen Calibration mtx:", mtx)
  93. # print("Screen Calibration dist:", dist)
  94. # print("camera Calibration mtx1:", cam_mtx)
  95. # print("Screen Calibration dist1:", cam_dist)
  96. # print("*"*100)
  97. mat_data = {
  98. 'screen_matrix': mtx,
  99. 'screen_distortion': dist,
  100. 'screen_rotation_matrix': R,
  101. 'screen_translation_vector': T,
  102. 'screen_error': ret/len(objpoints)
  103. }
  104. return mat_data