stitcher_keypoint.py 3.4 KB

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