| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- # -*- coding: utf-8 -*-
- """
- 切割漫画格子图片
- """
- import sys
- import json
- import cv2
- import numpy as np
- from pathlib import Path
- # Windows编码修复
- if sys.platform == 'win32':
- import io
- sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
- sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
- def cut_panels(image_path, panels_json_path, output_dir):
- """
- 切割漫画格子图片
-
- 参数:
- image_path: 原始图片路径
- panels_json_path: 格子信息JSON文件路径
- output_dir: 输出目录
- """
- image_path = Path(image_path)
- panels_json_path = Path(panels_json_path)
- output_dir = Path(output_dir)
- output_dir.mkdir(parents=True, exist_ok=True)
-
- # 读取原始图片
- print(f"📖 读取原始图片: {image_path.name}")
- img_array = np.fromfile(str(image_path), dtype=np.uint8)
- img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
-
- if img is None:
- raise ValueError(f"无法读取图片: {image_path}")
-
- img_height, img_width = img.shape[:2]
- print(f"[INFO] 图片尺寸: {img_width}x{img_height}")
-
- # 读取格子信息
- print(f"📋 读取格子信息: {panels_json_path.name}")
- with open(panels_json_path, 'r', encoding='utf-8') as f:
- panels_data = json.load(f)
-
- panels = panels_data.get('panels', [])
- if len(panels) == 0:
- raise ValueError("未找到任何格子信息")
-
- print(f"[INFO] 找到 {len(panels)} 个格子")
-
- # 按照从右到左、从上到下的顺序排序格子
- sorted_panels = sorted(panels, key=lambda p: (p['center_y'], -p['center_x']))
-
- # 切割每个格子
- for idx, panel in enumerate(sorted_panels, 1):
- x = max(0, int(panel['x']))
- y = max(0, int(panel['y']))
- w = min(int(panel['width']), img_width - x)
- h = min(int(panel['height']), img_height - y)
-
- if w <= 0 or h <= 0:
- print(f"[WARN] 跳过无效格子 {idx}: x={x}, y={y}, w={w}, h={h}")
- continue
-
- # 切割格子区域
- panel_img = img[y:y+h, x:x+w]
-
- # 保存切割后的图片
- output_filename = f"check{idx}.png"
- output_path = output_dir / output_filename
-
- # 使用cv2.imencode处理中文路径
- success, encoded_img = cv2.imencode('.png', panel_img)
- if success:
- encoded_img.tofile(str(output_path))
- print(f" [{idx}/{len(sorted_panels)}] 已保存: {output_filename} ({w}x{h})")
- else:
- print(f"[ERROR] 保存失败: {output_filename}")
-
- print(f"\n✅ 切割完成,共 {len(sorted_panels)} 个格子")
- if __name__ == '__main__':
- if len(sys.argv) < 4:
- print("用法: python cut_panels.py <原始图片路径> <格子信息JSON路径> <输出目录>")
- sys.exit(1)
-
- image_path = sys.argv[1]
- panels_json_path = sys.argv[2]
- output_dir = sys.argv[3]
-
- try:
- cut_panels(image_path, panels_json_path, output_dir)
- except Exception as e:
- print(f"[ERROR] 切割失败: {e}")
- import traceback
- traceback.print_exc()
- sys.exit(1)
|