From f0a70c256f6a6ecde6c3ae1f41849ee78a59fc8c Mon Sep 17 00:00:00 2001 From: Mika Date: Sun, 22 Mar 2026 03:08:31 +0000 Subject: [PATCH] Add image_processing/src/image_processing/cli.py --- image_processing/src/image_processing/cli.py | 81 ++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 image_processing/src/image_processing/cli.py diff --git a/image_processing/src/image_processing/cli.py b/image_processing/src/image_processing/cli.py new file mode 100644 index 0000000..5abf421 --- /dev/null +++ b/image_processing/src/image_processing/cli.py @@ -0,0 +1,81 @@ +import argparse +import sys +from pathlib import Path +import logging + +import numpy as np +import cv2 # noqa: F401 (used indirectly by core) + +from image_processing.core import process_images + + +def _validate_input_path(input_path: Path) -> Path: + if not input_path.exists() or not input_path.is_dir(): + raise FileNotFoundError(f"Input path '{input_path}' does not exist or is not a directory.") + return input_path + + +def _validate_output_path(output_path: Path) -> Path: + parent = output_path.parent + if not parent.exists(): + parent.mkdir(parents=True, exist_ok=True) + return output_path + + +def _collect_images_from_dir(directory: Path) -> list[str]: + image_files = sorted( + [str(p) for p in directory.glob('*.jpg') if p.is_file()] + ) + if not image_files: + raise ValueError(f"No .jpg images found in directory '{directory}'.") + return image_files + + +def main() -> None: + """Command-line entry point for image processing stacker.""" + parser = argparse.ArgumentParser( + description="Process and stack long-exposure images." + ) + parser.add_argument( + "--input", + required=True, + help="Pfad zum Ordner mit Eingabebildern.", + ) + parser.add_argument( + "--output", + required=True, + help="Pfad zur Ausgabedatei für das Ergebnisbild.", + ) + + args = parser.parse_args() + + logging.basicConfig( + level=logging.INFO, + format="[%(asctime)s] %(levelname)s:%(name)s: %(message)s", + ) + logger = logging.getLogger("image_processing.cli") + + try: + input_path = _validate_input_path(Path(args.input)) + output_path = _validate_output_path(Path(args.output)) + image_files = _collect_images_from_dir(input_path) + + logger.info("Processing %d images from %s", len(image_files), input_path) + result_image = process_images(image_files) + + if not isinstance(result_image, np.ndarray): + raise TypeError("process_images did not return a numpy.ndarray") + + success = cv2.imwrite(str(output_path), result_image) + if not success: + raise IOError(f"Failed to write output image to '{output_path}'.") + + logger.info("Stacked image written to %s", output_path) + + except Exception as e: + logger.error("Error: %s", e) + sys.exit(1) + + +if __name__ == "__main__": + main()