Spaces:
Sleeping
Sleeping
| """ | |
| Image refinement functionality. | |
| """ | |
| import os | |
| import cv2 | |
| import numpy as np | |
| from loguru import logger | |
| from .splitter import create_output_directory | |
| def refine_animal_illustrations(input_dir='split_animals', refined_dir='refined_animals'): | |
| """ | |
| Refine the extracted animal illustrations by removing excess whitespace. | |
| Args: | |
| input_dir (str): Directory containing the initially split animal images | |
| refined_dir (str): Directory where refined animal images will be saved | |
| Returns: | |
| list: Paths to the refined animal images | |
| """ | |
| # Create refined output directory | |
| refined_dir = create_output_directory(refined_dir) | |
| refined_paths = [] | |
| # Process each file in the input directory | |
| for filename in os.listdir(input_dir): | |
| if not filename.lower().endswith(('.png', '.jpg', '.jpeg')): | |
| continue | |
| file_path = os.path.join(input_dir, filename) | |
| try: | |
| # Read image | |
| img = cv2.imread(file_path) | |
| if img is None: | |
| logger.warning(f"Could not read image: {file_path}") | |
| continue | |
| # Process image | |
| refined_img = remove_excess_whitespace(img) | |
| # Save refined image | |
| refined_path = os.path.join(refined_dir, filename) | |
| cv2.imwrite(refined_path, refined_img) | |
| refined_paths.append(refined_path) | |
| logger.info(f"Refined: {refined_path}") | |
| except Exception as e: | |
| logger.error(f"Error processing {file_path}: {str(e)}") | |
| continue | |
| logger.info(f"Refinement complete. Images saved to {refined_dir}") | |
| return refined_paths | |
| def remove_excess_whitespace(img, padding=10): | |
| """ | |
| Remove excess whitespace around the main content of an image. | |
| Args: | |
| img (numpy.ndarray): Input image | |
| padding (int): Padding to add around content | |
| Returns: | |
| numpy.ndarray: Cropped image | |
| """ | |
| # Convert to grayscale | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| # Apply threshold to separate content from background | |
| _, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV) | |
| # Find contours | |
| contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| if not contours: | |
| return img | |
| # Find largest contour (assumed to be the main content) | |
| largest_contour = max(contours, key=cv2.contourArea) | |
| # Get bounding rectangle | |
| x, y, w, h = cv2.boundingRect(largest_contour) | |
| # Add padding | |
| x = max(0, x - padding) | |
| y = max(0, y - padding) | |
| w = min(img.shape[1] - x, w + 2 * padding) | |
| h = min(img.shape[0] - y, h + 2 * padding) | |
| # Crop image | |
| return img[y:y+h, x:x+w] | |
| def calculate_content_bounds(gray_img, threshold=240): | |
| """ | |
| Calculate content boundaries in grayscale image. | |
| Args: | |
| gray_img (numpy.ndarray): Grayscale image | |
| threshold (int): Brightness threshold | |
| Returns: | |
| tuple: (min_x, min_y, max_x, max_y) | |
| """ | |
| # Create binary mask | |
| _, mask = cv2.threshold(gray_img, threshold, 255, cv2.THRESH_BINARY_INV) | |
| # Find non-zero points | |
| points = cv2.findNonZero(mask) | |
| if points is None: | |
| return None | |
| # Calculate bounds | |
| x, y, w, h = cv2.boundingRect(points) | |
| return (x, y, x + w, y + h) | |