cut_panels.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. # -*- coding: utf-8 -*-
  2. """
  3. 切割漫画格子图片
  4. """
  5. import sys
  6. import json
  7. import cv2
  8. import numpy as np
  9. from pathlib import Path
  10. # Windows编码修复
  11. if sys.platform == 'win32':
  12. import io
  13. sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
  14. sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
  15. def cut_panels(image_path, panels_json_path, output_dir):
  16. """
  17. 切割漫画格子图片
  18. 参数:
  19. image_path: 原始图片路径
  20. panels_json_path: 格子信息JSON文件路径
  21. output_dir: 输出目录
  22. """
  23. image_path = Path(image_path)
  24. panels_json_path = Path(panels_json_path)
  25. output_dir = Path(output_dir)
  26. output_dir.mkdir(parents=True, exist_ok=True)
  27. # 读取原始图片
  28. print(f"📖 读取原始图片: {image_path.name}")
  29. img_array = np.fromfile(str(image_path), dtype=np.uint8)
  30. img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
  31. if img is None:
  32. raise ValueError(f"无法读取图片: {image_path}")
  33. img_height, img_width = img.shape[:2]
  34. print(f"[INFO] 图片尺寸: {img_width}x{img_height}")
  35. # 读取格子信息
  36. print(f"📋 读取格子信息: {panels_json_path.name}")
  37. with open(panels_json_path, 'r', encoding='utf-8') as f:
  38. panels_data = json.load(f)
  39. panels = panels_data.get('panels', [])
  40. if len(panels) == 0:
  41. raise ValueError("未找到任何格子信息")
  42. print(f"[INFO] 找到 {len(panels)} 个格子")
  43. # 按照从右到左、从上到下的顺序排序格子
  44. sorted_panels = sorted(panels, key=lambda p: (p['center_y'], -p['center_x']))
  45. # 切割每个格子
  46. for idx, panel in enumerate(sorted_panels, 1):
  47. x = max(0, int(panel['x']))
  48. y = max(0, int(panel['y']))
  49. w = min(int(panel['width']), img_width - x)
  50. h = min(int(panel['height']), img_height - y)
  51. if w <= 0 or h <= 0:
  52. print(f"[WARN] 跳过无效格子 {idx}: x={x}, y={y}, w={w}, h={h}")
  53. continue
  54. # 切割格子区域
  55. panel_img = img[y:y+h, x:x+w]
  56. # 保存切割后的图片
  57. output_filename = f"check{idx}.png"
  58. output_path = output_dir / output_filename
  59. # 使用cv2.imencode处理中文路径
  60. success, encoded_img = cv2.imencode('.png', panel_img)
  61. if success:
  62. encoded_img.tofile(str(output_path))
  63. print(f" [{idx}/{len(sorted_panels)}] 已保存: {output_filename} ({w}x{h})")
  64. else:
  65. print(f"[ERROR] 保存失败: {output_filename}")
  66. print(f"\n✅ 切割完成,共 {len(sorted_panels)} 个格子")
  67. if __name__ == '__main__':
  68. if len(sys.argv) < 4:
  69. print("用法: python cut_panels.py <原始图片路径> <格子信息JSON路径> <输出目录>")
  70. sys.exit(1)
  71. image_path = sys.argv[1]
  72. panels_json_path = sys.argv[2]
  73. output_dir = sys.argv[3]
  74. try:
  75. cut_panels(image_path, panels_json_path, output_dir)
  76. except Exception as e:
  77. print(f"[ERROR] 切割失败: {e}")
  78. import traceback
  79. traceback.print_exc()
  80. sys.exit(1)