xenium_cell_segmentation / utils /generate_split_images.py
unikill066's picture
Upload 29 files
c843d82 verified
#!/usr/bin/env python3
"""
Developed by Nikhil Nageshwar Inturi
This module provides ImageSplitter for splitting PNG images into
equal-sized sub-images and saving them to an output directory.
"""
# imports
from pathlib import Path
import numpy as np, cv2, logging
from PIL import Image
# local imports
from utils.constants import setup_logging
Image.MAX_IMAGE_PIXELS = None
class ImageSplitter:
"""
Splits all PNG images in a source directory into sub-images of specified width and height.
"""
def __init__(self, source_dir: Path, output_dir: Path, sub_image_width: int, sub_image_height: int) -> None:
self.source_dir = Path(source_dir)
self.output_dir = Path(output_dir)
self.sub_w = sub_image_width
self.sub_h = sub_image_height
self.logger = logging.getLogger(self.__class__.__name__)
self._setup_output_directory()
def _setup_output_directory(self) -> None:
try:
self.output_dir.mkdir(parents=True, exist_ok=True)
self.logger.debug(f"Output directory ready: {self.output_dir}")
except Exception as e:
self.logger.error(f"Failed to create output directory {self.output_dir}: {e}")
raise
def split_all(self) -> None:
"""
Iterate over all PNG files in source_dir and split them.
"""
png_files = list(self.source_dir.glob("*.png"))
if not png_files:
self.logger.warning(f"No .png files found in {self.source_dir}")
return
for png_file in png_files:
try:
self.split_file(png_file)
except Exception:
self.logger.exception(f"Error splitting file: {png_file}")
def split_file(self, png_path: Path) -> None:
"""
Split a single PNG image into sub-images.
Args:
png_path: Path to the input .png file.
"""
with Image.open(png_path) as pil_img:
img = np.array(pil_img)
self.logger.debug(f"Loaded {png_path.name} with shape {img.shape}")
height, width = img.shape[:2]
cols = (width + self.sub_w - 1) // self.sub_w
rows = (height + self.sub_h - 1) // self.sub_h
for row in range(rows):
for col in range(cols):
x0 = col * self.sub_w
y0 = row * self.sub_h
x1 = min(x0 + self.sub_w, width)
y1 = min(y0 + self.sub_h, height)
sub_img = img[y0:y1, x0:x1]
output_name = f"{png_path.stem}_{row}_{col}.png"
output_path = self.output_dir / output_name
# success = cv2.imwrite(str(output_path), sub_img)
sub_img_bgr = cv2.cvtColor(sub_img, cv2.COLOR_RGB2BGR)
success = cv2.imwrite(str(output_path), sub_img_bgr)
if success:
self.logger.info(f"Saved sub-image: {output_name}")
else:
self.logger.error(f"Failed to save sub-image: {output_name}")
# testing
# from bin.constants import setup_logging
# from bin.generate_split_images import ImageSplitter
# setup_logging(logging.INFO)
# splitter = ImageSplitter(source_dir=Path("path/to/pngs"), output_dir=Path("path/to/splits"), sub_image_width=640, sub_image_height=640)
# splitter.split_all()