0_generate_fringe.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import os
  4. def calculate_phase(images):
  5. images = np.array(images)
  6. shifts = len(images)
  7. phase = np.arctan2(np.sum(images * np.sin(np.linspace(0, 2 * np.pi, shifts)[:, np.newaxis, np.newaxis]), axis=0),
  8. np.sum(images * np.cos(np.linspace(0, 2 * np.pi, shifts)[:, np.newaxis, np.newaxis]), axis=0))
  9. return phase
  10. def unwrap_phase(phase):
  11. unwrapped_phase = np.unwrap(phase, axis=0)
  12. unwrapped_phase = np.unwrap(unwrapped_phase, axis=1)
  13. return unwrapped_phase
  14. def find_subpixel_extrema(phase_map):
  15. # 找到最大值和最小值的索引
  16. min_pos = np.unravel_index(np.argmin(phase_map), phase_map.shape)
  17. max_pos = np.unravel_index(np.argmax(phase_map), phase_map.shape)
  18. # 返回亚像素坐标
  19. return np.array(min_pos), np.array(max_pos)
  20. def generate_phase_shifted_patterns(width, height, shifts, orientation='horizontal', frequency=1):
  21. """
  22. Generates multiple phase-shifted fringe patterns, either horizontal or vertical, with phase shifting along the stripes.
  23. :param width: image width
  24. :param height: image height
  25. :param shifts: number of phase shifts
  26. :param orientation: 'horizontal' or 'vertical' indicating the direction of the stripes
  27. :param frequency: number of full wave cycles across the dimension
  28. :return: array of generated fringe patterns
  29. """
  30. patterns = []
  31. for i in range(shifts):
  32. shift = (i * 2 * np.pi) / shifts # Calculating the phase shift for each pattern
  33. if orientation == 'horizontal':
  34. x = np.linspace(0, 2 * np.pi * frequency, width) + shift # Apply frequency scaling on horizontal stripes
  35. print('frequency, horizontal x = ', x, frequency)
  36. print('step = ', 2 * np.pi * frequency )
  37. pattern = np.sin(x)
  38. print('pattern = ', pattern)
  39. pattern = np.tile(pattern, (height, 1)) # Extend the pattern vertically across the height
  40. elif orientation == 'vertical':
  41. y = np.linspace(0, 2 * np.pi * frequency, height) + shift # Apply frequency scaling on vertical stripes
  42. pattern = np.sin(y)
  43. pattern = np.tile(pattern.reshape(-1, 1), (1, width)) # Extend the pattern horizontally across the width
  44. patterns.append(pattern)
  45. return patterns
  46. # Image size parameters
  47. width = 1920
  48. height = 1200
  49. width = 800
  50. height = 400
  51. shifts = 4 # Number of phase shifts
  52. frequencies = [32, 8 ,1] # Two different frequencies
  53. #frequencies = [32, 1] # Two different frequencies
  54. # Ensure the directory exists
  55. directory = 'patterns3_honor_800_400'
  56. os.makedirs(directory, exist_ok=True)
  57. # Pattern naming and saving
  58. pattern_index = 0 # Start indexing from 0
  59. for freq in frequencies:
  60. # Generate horizontal patterns first, then vertical for each frequency
  61. horizontal_patterns = generate_phase_shifted_patterns(width, height, shifts, 'horizontal', freq)
  62. vertical_patterns = generate_phase_shifted_patterns(width, height, shifts, 'vertical', freq)
  63. all_patterns = horizontal_patterns + vertical_patterns # Combine lists to maintain the order
  64. # phase = np.arctan2(
  65. # np.sum(horizontal_patterns * np.sin(np.linspace(0, 2 * np.pi, shifts)[:, np.newaxis, np.newaxis]), axis=0),
  66. # np.sum(horizontal_patterns * np.cos(np.linspace(0, 2 * np.pi, shifts)[:, np.newaxis, np.newaxis]), axis=0)
  67. # )
  68. # print('截断相位 = ', phase)
  69. # y_coords, x_coords = np.meshgrid(np.arange(height), np.arange(width), indexing='ij')
  70. # # 提取所有像素坐标和截断相位值
  71. # coordinates = np.stack((y_coords, x_coords), axis=-1) # 生成每个像素的坐标
  72. # target_mask = (phase >= -1) & (phase <= 1)
  73. # target_coordinates = coordinates[target_mask] # 提取目标范围内的像素坐标
  74. # print("对应的像素坐标:", target_coordinates)
  75. # # 可视化截断相位
  76. # plt.imshow(phase, cmap='jet')
  77. # plt.colorbar(label='Phase (wrapped)')
  78. # plt.scatter(target_coordinates[:, 1], target_coordinates[:, 0], color='red', s=1, label='Target Pixels')
  79. # plt.title("Wrapped Phase with Target Pixels")
  80. # plt.legend()
  81. # plt.show()
  82. # 计算相位图
  83. # phase_map = calculate_phase(horizontal_patterns)
  84. # # 展开相位图
  85. # unwrapped_phase_map = unwrap_phase(phase_map)
  86. # print('unwrapped_phase_map = ', unwrapped_phase_map.shape)
  87. # # 找到亚像素级别的极值点坐标
  88. # min_subpixel, max_subpixel = find_subpixel_extrema(unwrapped_phase_map)
  89. # # 可视化相位图并标注极值点
  90. # plt.imshow(unwrapped_phase_map, cmap='jet')
  91. # plt.colorbar()
  92. # plt.scatter([min_subpixel[1]], [min_subpixel[0]], color='red', label='Min')
  93. # plt.scatter([max_subpixel[1]], [max_subpixel[0]], color='blue', label='Max')
  94. # plt.legend()
  95. # plt.title("Unwrapped Phase Map with Extremes")
  96. # plt.show()
  97. # print(f"Min subpixel position: {min_subpixel}")
  98. # print(f"Max subpixel position: {max_subpixel}")
  99. # Save the patterns with the new naming convention in the specified directory
  100. for pattern in all_patterns:
  101. file_path = os.path.join(directory, f'pat{pattern_index:02}.bmp')
  102. print('pattern shape =',pattern.shape)
  103. print(pattern)
  104. plt.imsave(file_path, pattern, cmap='gray')
  105. pattern_index += 1