stitcher_template.py 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import cv2
  2. import logging
  3. from pathlib import Path
  4. from tqdm import tqdm
  5. from fry_project_classes.stitch_img_template_match import ImageStitcherTemplateMatch
  6. from fry_project_classes.get_full_stitch_order import get_full_stitch_order
  7. from utils.utils import natural_sort_key
  8. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  9. def stitch_img(IMAGE_DIR: Path, OUTPUT_DIR: Path, NUM_COLS: int, NUM_ROWS: int,
  10. ESTIMATE_OVERLAP_HORIZONTAL_PIXELS: int, ESTIMATE_OVERLAP_VERTICAL_PIXELS: int,
  11. BLEND_TYPE: str, LIGHT_COMPENSATION: bool,
  12. # --- 新增的关键参数 ---
  13. BLEND_RATIO: float,
  14. LIGHT_COMPENSATION_WIDTH: int,
  15. DEBUG_MODE: bool) -> Path | None:
  16. """
  17. 基于模板匹配的图像拼接函数,使用优化的拼接顺序。
  18. 成功时返回最终图像的路径,失败时返回 None。
  19. """
  20. OUTPUT_DIR.mkdir(exist_ok=True, parents=True)
  21. logging.info("--- [模板匹配] 图像拼接开始 (优化顺序) ---")
  22. # 1. 加载并排序所有图片
  23. image_paths = sorted(list(IMAGE_DIR.glob("*.*")), key=natural_sort_key) # 支持更多图片格式
  24. if len(image_paths) < NUM_COLS * NUM_ROWS:
  25. logging.error(f"错误: 找到 {len(image_paths)} 张图片, 但预期需要 {NUM_COLS * NUM_ROWS} 张。")
  26. return None
  27. images_dict = {}
  28. for i, path in enumerate(image_paths):
  29. img = cv2.imread(str(path))
  30. if img is None:
  31. logging.error(f"错误: 无法读取图片 {path}")
  32. return None
  33. images_dict[str(i + 1)] = img
  34. # 2. 获取拼接顺序
  35. full_stitch_order_dict = get_full_stitch_order(NUM_ROWS, NUM_COLS)
  36. logging.info(f"获取到 {len(full_stitch_order_dict)} 步拼接指令")
  37. # 3. 按照指令集执行拼接
  38. final_image = None
  39. iterator = tqdm(full_stitch_order_dict.items(), desc="[模板]执行拼接", total=len(full_stitch_order_dict))
  40. for step, (round_num, img1_name, img2_name, direction, result_name) in iterator:
  41. img1 = images_dict[img1_name]
  42. img2 = images_dict[img2_name]
  43. overlap_pixels = ESTIMATE_OVERLAP_HORIZONTAL_PIXELS if direction == 'horizontal' else ESTIMATE_OVERLAP_VERTICAL_PIXELS
  44. stitcher = ImageStitcherTemplateMatch(
  45. estimate_overlap_pixels=overlap_pixels,
  46. stitch_type=direction,
  47. blend_type=BLEND_TYPE,
  48. blend_ratio=BLEND_RATIO,
  49. light_uniformity_compensation_enabled=LIGHT_COMPENSATION,
  50. light_uniformity_compensation_width=LIGHT_COMPENSATION_WIDTH,
  51. debug=DEBUG_MODE,
  52. debug_dir=str(OUTPUT_DIR / f'debug_{result_name}')
  53. )
  54. stitched_image = stitcher.stitch_main(img1, img2)
  55. if stitched_image is None:
  56. logging.error(f"步骤 {step} 拼接失败: {img1_name} + {img2_name}")
  57. return None
  58. images_dict[result_name] = stitched_image
  59. final_image = stitched_image
  60. # 4. 保存并返回结果
  61. if final_image is not None:
  62. final_output_path = OUTPUT_DIR / "final_stitched_image.jpg"
  63. cv2.imwrite(str(final_output_path), final_image)
  64. logging.info(f"--- [模板匹配] 拼接任务完成!最终图已暂存至: {final_output_path} ---")
  65. return final_output_path
  66. else:
  67. logging.error("拼接失败,未能生成最终图像。")
  68. return None