pmd.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #encoding=utf-8
  2. import time
  3. import os
  4. import sys
  5. sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
  6. import time
  7. import glob
  8. import numpy as np
  9. np.random.seed(42)
  10. from datetime import datetime
  11. import json
  12. from src.utils import get_meshgrid, get_world_points, get_camera_points, get_screen_points, write_point_cloud, get_white_mask, get_meshgrid_contour, post_process
  13. from src.phase import extract_phase, unwrap_phase
  14. from src.recons import reconstruction_cumsum
  15. import matplotlib.pyplot as plt
  16. from src.calibration import calibrate_world, calibrate_screen, map_screen_to_world
  17. import argparse
  18. from src.vis import plot_coords
  19. import cv2
  20. from src.eval import get_eval_result, find_notch
  21. import pickle
  22. def pmdstart(config_path, img_folder):
  23. start_time = time.time()
  24. print(f"config_path: {config_path}")
  25. #time.sleep(15)
  26. main(config_path, img_folder)
  27. print(f"img_folder: {img_folder}")
  28. print('test pass')
  29. end_time = time.time()
  30. print(f"Time taken: {end_time - start_time} seconds")
  31. return True
  32. def main(config_path, img_folder):
  33. cfg = json.load(open(config_path, 'r'))
  34. n_cam = 4
  35. num_freq = cfg['num_freq']
  36. save_path = 'debug'
  37. debug = False
  38. grid_spacing = cfg['grid_spacing']
  39. num_freq = cfg['num_freq']
  40. smooth = True
  41. align = True
  42. denoise = True
  43. cammera_img_path = 'D:\\data\\four_cam\\calibrate\\calibration_0913'
  44. screen_img_path = 'D:\\data\\four_cam\\calibrate\\screen0920'
  45. print(f"开始执行时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  46. print("\n1. 相机标定")
  47. preprocess_start = time.time()
  48. cam_para_path = os.path.join('config', cfg['cam_params'])
  49. if os.path.exists(cam_para_path):
  50. #if False:
  51. with open(cam_para_path, 'rb') as pkl_file:
  52. cam_params = pickle.load(pkl_file)
  53. else:
  54. cam_params = []
  55. camera_subdir = [item for item in os.listdir(cammera_img_path) if os.path.isdir(os.path.join(cammera_img_path, item))]
  56. camera_subdir.sort()
  57. assert len(camera_subdir) == 4, f"found {len(camera_subdir)} cameras, should be 4"
  58. for i in range(n_cam):
  59. cam_img_path = glob.glob(os.path.join(cammera_img_path, camera_subdir[i], "*.bmp"))
  60. cam_img_path.sort()
  61. cam_param_raw = calibrate_world(cam_img_path, i, cfg['world_chessboard_size'], cfg['world_square_size'], debug=debug)
  62. cam_params.append(cam_param_raw)
  63. with open(cam_para_path, 'wb') as pkl_file:
  64. pickle.dump(cam_params, pkl_file)
  65. screen_img_path = glob.glob(os.path.join(screen_img_path, "*.bmp"))
  66. screen_para_path = os.path.join('config', cfg['screen_params'])
  67. if os.path.exists(screen_para_path):
  68. #if False:
  69. with open(screen_para_path, 'rb') as pkl_file:
  70. screen_params = pickle.load(pkl_file)[0]
  71. else:
  72. screen_params = calibrate_screen(screen_img_path, cam_params[0]['camera_matrix'], cam_params[0]['distortion_coefficients'], cfg['screen_chessboard_size'], cfg['screen_square_size'], debug=True)
  73. with open(screen_para_path, 'wb') as pkl_file:
  74. pickle.dump([screen_params], pkl_file)
  75. preprocess_end = time.time()
  76. print(f" 完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  77. print(f" 耗时: {preprocess_end - preprocess_start:.2f} 秒")
  78. # import pdb; pdb.set_trace()
  79. print("\n2. 屏幕标定")
  80. screen_cal_start = time.time()
  81. screen_to_world = map_screen_to_world(screen_params, cam_params[0])
  82. screen_cal_end = time.time()
  83. print(f" 完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  84. print(f" 耗时: {screen_cal_end - screen_cal_start:.2f} 秒")
  85. print("\n3. 相位提取,相位展开")
  86. phase_start = time.time()
  87. x_uns, y_uns = [], []
  88. binary_masks = []
  89. for cam_id in range(n_cam):
  90. print('cam_id = ', cam_id)
  91. white_path = os.path.join(img_folder, f'{cam_id}_frame_24.bmp')
  92. binary = get_white_mask(white_path)
  93. binary_masks.append(binary)
  94. phases = extract_phase(img_folder, cam_id, binary, cam_params[cam_id]['camera_matrix'], cam_params[cam_id]['distortion_coefficients'], num_freq=num_freq)
  95. x_un, y_un = unwrap_phase(phases, save_path, num_freq, debug=False)
  96. x_uns.append(x_un)
  97. y_uns.append(y_un)
  98. phase_end = time.time()
  99. print(f" 完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  100. print(f" 耗时: {phase_end - phase_start:.2f} 秒")
  101. print("\n4. 获得不同坐标系下点的位置")
  102. get_point_start = time.time()
  103. total_cloud_point = np.empty((0, 3))
  104. for i in range(n_cam):
  105. contours_point = get_meshgrid_contour(binary_masks[i], grid_spacing, save_path, debug=False)
  106. world_points = get_world_points(contours_point, cam_params[i], i, grid_spacing, cfg['d'], save_path, debug=debug)
  107. camera_points, u_p, v_p = get_camera_points(world_points, cam_params[i], save_path, i, debug=debug)
  108. point_data = {'x_w': world_points[:, 0], 'y_w': world_points[:, 1], 'z_w': world_points[:, 2],
  109. 'x_c': camera_points[:, 0], 'y_c': camera_points[:, 1], 'z_c': camera_points[:, 2],
  110. 'u_p': u_p, 'v_p': v_p}
  111. screen_points = get_screen_points(point_data, x_uns[i], y_uns[i], screen_params, screen_to_world, cfg, save_path, i, debug=debug)
  112. #plot_coords(world_points, camera_points, screen_points)
  113. z, smoothed, aligned, denoised = reconstruction_cumsum(world_points, camera_points, screen_points, save_path, i, debug=False, smooth=smooth, align=align, denoise=denoise)
  114. write_point_cloud(os.path.join(img_folder, str(i) + '_cloudpoint.txt'), world_points[:, 0], world_points[:, 1], 1000 * z)
  115. total_cloud_point = np.vstack([total_cloud_point, np.column_stack((world_points[:, 0], world_points[:, 1], 1000 * z))])
  116. if 1:
  117. fig = plt.figure()
  118. ax = fig.add_subplot(111, projection='3d')
  119. # 提取 x, y, z 坐标
  120. x_vals = total_cloud_point[:, 0]
  121. y_vals = total_cloud_point[:, 1]
  122. z_vals = total_cloud_point[:, 2]
  123. # 绘制3D点云
  124. ax.scatter(x_vals, y_vals, z_vals, c=z_vals, cmap='viridis', marker='o')
  125. # 设置轴标签和标题
  126. ax.set_xlabel('X (mm)')
  127. ax.set_ylabel('Y (mm)')
  128. ax.set_zlabel('Z (mm)')
  129. ax.set_title('3D Point Cloud Visualization')
  130. plt.show()
  131. get_point_end = time.time()
  132. print(f" 完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  133. print(f" 耗时: {get_point_end - get_point_start:.2f} 秒")
  134. print("\n5. 后处理")
  135. post_process_start = time.time()
  136. #total_cloud_point = post_process(img_folder, debug=True)
  137. #write_point_cloud(os.path.join(img_folder, 'cloudpoint.txt'), total_cloud_point[:, 0], total_cloud_point[:, 1], total_cloud_point[:,2])
  138. post_process_end = time.time()
  139. print(f" 完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  140. print(f" 耗时: {post_process_end - post_process_start:.2f} 秒")
  141. print("\n6. 评估")
  142. eval_start = time.time()
  143. point_cloud_path = os.path.join(img_folder, 'cloudpoint.txt')
  144. json_path = os.path.join(img_folder, 'result.json')
  145. theta_notch = 0
  146. get_eval_result(point_cloud_path, json_path, theta_notch, 0)
  147. eval_end = time.time()
  148. print(f" 完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  149. print(f" 耗时: {eval_end - eval_start:.2f} 秒")
  150. return True
  151. if __name__ == '__main__':
  152. config_path = 'config\\cfg_3freq_wafer.json'
  153. img_folder = 'D:\\data\\four_cam\\0927_storage\\20240927161651920'
  154. pmdstart(config_path, img_folder)