extract_panel_with_green_boxes.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. # -*- coding: utf-8 -*-
  2. """
  3. 从带绿色线框的完整图片中提取格子区域,并在格子图片上绘制对应的绿色线框
  4. """
  5. import sys
  6. import cv2
  7. import numpy as np
  8. from pathlib import Path
  9. # Windows编码修复
  10. if sys.platform == 'win32':
  11. import io
  12. sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
  13. sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
  14. def extract_panel_with_green_boxes(full_image_path, panel_image_path, output_path,
  15. panel_x, panel_y, panel_width, panel_height):
  16. """
  17. 从完整图片中提取格子区域,并在格子图片上绘制对应的绿色线框
  18. 参数:
  19. full_image_path: 带绿色线框的完整图片路径
  20. panel_image_path: 格子图片路径(原图)
  21. output_path: 输出图片路径(带绿色线框的格子图片)
  22. panel_x, panel_y, panel_width, panel_height: 格子在完整图片中的坐标
  23. """
  24. # 读取完整图片(带绿色线框)
  25. full_img_array = np.fromfile(str(full_image_path), dtype=np.uint8)
  26. full_img = cv2.imdecode(full_img_array, cv2.IMREAD_COLOR)
  27. if full_img is None:
  28. raise ValueError(f"无法读取完整图片: {full_image_path}")
  29. # 读取格子图片(原图)
  30. panel_img_array = np.fromfile(str(panel_image_path), dtype=np.uint8)
  31. panel_img = cv2.imdecode(panel_img_array, cv2.IMREAD_COLOR)
  32. if panel_img is None:
  33. raise ValueError(f"无法读取格子图片: {panel_image_path}")
  34. print(f"[INFO] 完整图片尺寸: {full_img.shape[1]}x{full_img.shape[0]}")
  35. print(f"[INFO] 格子图片尺寸: {panel_img.shape[1]}x{panel_img.shape[0]}")
  36. print(f"[INFO] 格子坐标: x={panel_x}, y={panel_y}, w={panel_width}, h={panel_height}")
  37. # 从完整图片中提取格子区域的绿色线框
  38. panel_region = full_img[panel_y:panel_y + panel_height, panel_x:panel_x + panel_width]
  39. # 检测绿色像素(BGR格式:绿色为 (0, 255, 0))
  40. green_color_lower = np.array([0, 200, 0])
  41. green_color_upper = np.array([50, 255, 50])
  42. green_mask = cv2.inRange(panel_region, green_color_lower, green_color_upper)
  43. # 形态学操作,连接断开的绿色线条
  44. kernel = np.ones((3, 3), np.uint8)
  45. green_mask = cv2.morphologyEx(green_mask, cv2.MORPH_CLOSE, kernel, iterations=2)
  46. green_mask = cv2.dilate(green_mask, kernel, iterations=1)
  47. # 使用轮廓检测找到绿色框
  48. contours, _ = cv2.findContours(green_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  49. print(f"[INFO] 在格子区域检测到 {len(contours)} 个绿色轮廓")
  50. # 在格子图片上绘制绿色线框
  51. result_img = panel_img.copy()
  52. green_boxes = []
  53. for i, contour in enumerate(contours):
  54. # 计算边界框
  55. x, y, box_w, box_h = cv2.boundingRect(contour)
  56. # 过滤太小的区域
  57. min_area = panel_img.shape[0] * panel_img.shape[1] * 0.001
  58. if box_w * box_h < min_area:
  59. continue
  60. # 过滤太细的线
  61. if box_w < 5 or box_h < 5:
  62. continue
  63. # 绘制绿色矩形框
  64. cv2.rectangle(result_img, (x, y), (x + box_w, y + box_h), (0, 255, 0), 2)
  65. # 标注序号
  66. label = str(i + 1)
  67. font = cv2.FONT_HERSHEY_SIMPLEX
  68. font_scale = 0.6
  69. font_thickness = 1
  70. (text_width, text_height), baseline = cv2.getTextSize(label, font, font_scale, font_thickness)
  71. # 在左上角绘制文字背景(白色矩形)
  72. cv2.rectangle(result_img, (x, y - text_height - baseline - 2),
  73. (x + text_width, y), (255, 255, 255), -1)
  74. # 绘制文字(绿色)
  75. cv2.putText(result_img, label, (x, y - baseline - 2),
  76. font, font_scale, (0, 255, 0), font_thickness, cv2.LINE_AA)
  77. green_boxes.append({
  78. 'x1': x,
  79. 'y1': y,
  80. 'x2': x + box_w,
  81. 'y2': y + box_h
  82. })
  83. print(f"[INFO] 在格子图片上绘制了 {len(green_boxes)} 个绿色框")
  84. # 保存结果
  85. success, encoded_img = cv2.imencode('.png', result_img)
  86. if success:
  87. encoded_img.tofile(str(output_path))
  88. print(f"[OK] 已保存带绿色线框的格子图片: {output_path}")
  89. return True
  90. else:
  91. print(f"[ERROR] 保存图片失败: {output_path}")
  92. return False
  93. if __name__ == '__main__':
  94. if len(sys.argv) < 8:
  95. print("用法: python extract_panel_with_green_boxes.py <full_image_path> <panel_image_path> <output_path> <panel_x> <panel_y> <panel_width> <panel_height>")
  96. print("示例: python extract_panel_with_green_boxes.py full.png panel.png output.png 0 0 750 746")
  97. sys.exit(1)
  98. full_image_path = sys.argv[1]
  99. panel_image_path = sys.argv[2]
  100. output_path = sys.argv[3]
  101. panel_x = int(sys.argv[4])
  102. panel_y = int(sys.argv[5])
  103. panel_width = int(sys.argv[6])
  104. panel_height = int(sys.argv[7])
  105. success = extract_panel_with_green_boxes(
  106. full_image_path, panel_image_path, output_path,
  107. panel_x, panel_y, panel_width, panel_height
  108. )
  109. sys.exit(0 if success else 1)