From f8e54d0f8b0fd34cb63bbcc10d6a2f2f7bf05cf3 Mon Sep 17 00:00:00 2001 From: Daniel Bedeleanu Date: Wed, 22 Apr 2026 08:58:17 +0300 Subject: [PATCH] fix: apply rotation before cropping for better text orientation - Move manual rotation before cropping and text detection - Detect text orientation on full rotated image (not just cropped region) - This allows text angle detection to see full context and properly orient labels - Crop happens after orientation correction for cleaner results --- backend/services/image_processing.py | 35 +++++++++++----------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/backend/services/image_processing.py b/backend/services/image_processing.py index e9282544..8c8e8fb2 100644 --- a/backend/services/image_processing.py +++ b/backend/services/image_processing.py @@ -88,10 +88,21 @@ class ImageProcessor: image = self._rotate_by_orientation(image, exif_orientation) self.logger.info(f"Applied EXIF rotation: {exif_orientation}") - # Smart cropping + # Apply manual rotation FIRST (before cropping/detection) + if abs(rotation_degrees) > 0.5: + image = image.rotate(-rotation_degrees, expand=True) + self.logger.info(f"Applied manual rotation: {rotation_degrees}°") + + # Detect text orientation on full rotated image (before cropping) + text_angle, angle_status = self._detect_text_orientation(image) + if text_angle is not None: + self.logger.info(f"Detected text angle: {text_angle}° ({angle_status})") + if angle_status in ['upside_down', 'sideways']: + image = self._rotate_image(image, text_angle) + + # Now crop after orientation is corrected cropped_image = image crop_size = None - text_angle = None crop_method = 'none' if crop_bounds: @@ -108,26 +119,13 @@ class ImageProcessor: crop_method = 'manual' self.logger.info(f"Applied manual crop: {crop_size}") else: - # Try OpenCV smart crop + # Try OpenCV smart crop on properly oriented image try: crop_result = self._smart_crop_opencv(image) if crop_result is not None: cropped_image, crop_size = crop_result crop_method = 'opencv' self.logger.info(f"Applied OpenCV crop: {crop_size}") - - # Detect text orientation within the cropped region - text_angle, angle_status = self._detect_text_orientation( - cropped_image - ) - if text_angle is not None: - self.logger.info( - f"Detected text angle: {text_angle}° ({angle_status})" - ) - if angle_status in ['upside_down', 'sideways']: - cropped_image = self._rotate_image( - cropped_image, text_angle - ) else: crop_method = 'pillow' except (IOError, ValueError, cv2.error) as e: @@ -137,11 +135,6 @@ class ImageProcessor: ) crop_method = 'pillow' - # Apply manual rotation if provided - if abs(rotation_degrees) > 0.5: - cropped_image = cropped_image.rotate(-rotation_degrees, expand=True) - self.logger.info(f"Applied manual rotation: {rotation_degrees}°") - # Resize and compress compressed_bytes = self._resize_and_compress(cropped_image)