|
|
import cv2 |
|
|
import numpy as np |
|
|
import os |
|
|
import time |
|
|
from datetime import datetime |
|
|
|
|
|
|
|
|
def log_execution(func): |
|
|
def wrapper(*args, **kwargs): |
|
|
start_time = time.time() |
|
|
start_str = datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S') |
|
|
|
|
|
result = func(*args, **kwargs) |
|
|
|
|
|
end_time = time.time() |
|
|
end_str = datetime.fromtimestamp(end_time).strftime('%Y-%m-%d %H:%M:%S') |
|
|
duration = end_time - start_time |
|
|
|
|
|
return result |
|
|
return wrapper |
|
|
|
|
|
@log_execution |
|
|
def split_comic_panels(image_path, output_dir): |
|
|
img = cv2.imread(image_path) |
|
|
if img is None: |
|
|
print(f"Error: Could not read image from {image_path}") |
|
|
return |
|
|
|
|
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
|
|
|
|
|
th = cv2.adaptiveThreshold(gray, 255, |
|
|
cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, |
|
|
blockSize=51, C=10) |
|
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,15)) |
|
|
clean = cv2.morphologyEx(th, cv2.MORPH_CLOSE, kernel) |
|
|
|
|
|
cnts, _ = cv2.findContours(clean, cv2.RETR_EXTERNAL, |
|
|
cv2.CHAIN_APPROX_SIMPLE) |
|
|
panels = [] |
|
|
for c in cnts: |
|
|
area = cv2.contourArea(c) |
|
|
if area < 10000: |
|
|
continue |
|
|
peri = cv2.arcLength(c, True) |
|
|
approx = cv2.approxPolyDP(c, 0.02 * peri, True) |
|
|
panels.append((cv2.boundingRect(approx), c)) |
|
|
@log_execution |
|
|
def panel_key(item): |
|
|
(x,y,w,h), _ = item |
|
|
return (y//50, x) |
|
|
|
|
|
panels_sorted = sorted(panels, key=panel_key) |
|
|
|
|
|
if not os.path.exists(output_dir): |
|
|
os.makedirs(output_dir) |
|
|
|
|
|
for i, ((x,y,w,h), contour) in enumerate(panels_sorted, 1): |
|
|
crop = img[y:y+h, x:x+w] |
|
|
cv2.imwrite(os.path.join(output_dir, f"panel_{i:02d}.png"), crop) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
if not os.path.exists("comic_page.jpg"): |
|
|
dummy_image = np.zeros((600, 800, 3), dtype=np.uint8) |
|
|
cv2.putText(dummy_image, "Comic Page", (300, 300), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA) |
|
|
cv2.rectangle(dummy_image, (50, 50), (350, 250), (255,255,255), 5) |
|
|
cv2.rectangle(dummy_image, (400, 50), (750, 250), (255,255,255), 5) |
|
|
cv2.rectangle(dummy_image, (50, 300), (750, 550), (255,255,255), 5) |
|
|
cv2.imwrite("comic_page.jpg", dummy_image) |
|
|
|
|
|
if not os.path.exists("output_panels"): |
|
|
os.makedirs("output_panels") |
|
|
split_comic_panels("comic_page.jpg", "output_panels") |
|
|
print("Comic panels split and saved to output_panels directory.") |