From beaafbfaa8fdcafe7cd9fbf9b1d497710a19bc55 Mon Sep 17 00:00:00 2001 From: hoobnn <111053672+hoobnn@users.noreply.github.com> Date: Mon, 31 Aug 2026 09:26:01 +0800 Subject: [PATCH] feat: warn on large text detector inputs --- .../text_detection/_large_input_warning.py | 37 +++++++++++ .../models/text_detection/processors.py | 4 ++ .../models/text_detection/test_processors.py | 66 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 paddlex/inference/models/text_detection/_large_input_warning.py create mode 100644 tests/inference/models/text_detection/test_processors.py diff --git a/paddlex/inference/models/text_detection/_large_input_warning.py b/paddlex/inference/models/text_detection/_large_input_warning.py new file mode 100644 index 0000000000..ab5b487e53 --- /dev/null +++ b/paddlex/inference/models/text_detection/_large_input_warning.py @@ -0,0 +1,37 @@ +# Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +LARGE_DET_INPUT_WARN_PIXELS = 4_000_000 + + +class LargeDetectorInputWarner: + def __init__(self): + self._emitted = False + + def warn(self, source_shape, detector_shape, warning): + detector_h, detector_w = detector_shape[:2] + if self._emitted or detector_h * detector_w <= LARGE_DET_INPUT_WARN_PIXELS: + return + + source_h, source_w = source_shape[:2] + self._emitted = True + warning( + f"Text detection preprocessing produced a large detector input of " + f"{detector_w}x{detector_h} " + f"({detector_w * detector_h / 1e6:.1f} megapixels) from a " + f"{source_w}x{source_h} source image. This may increase memory use " + f"or cause an out-of-memory error. Consider lowering the detector " + f"input-size limits in the pipeline or model configuration." + ) diff --git a/paddlex/inference/models/text_detection/processors.py b/paddlex/inference/models/text_detection/processors.py index 23a38fdd65..e8b060e728 100644 --- a/paddlex/inference/models/text_detection/processors.py +++ b/paddlex/inference/models/text_detection/processors.py @@ -20,6 +20,7 @@ from ....utils import logging from ....utils.deps import class_requires_deps, is_dep_available from ...utils.benchmark import benchmark +from ._large_input_warning import LargeDetectorInputWarner if is_dep_available("opencv-contrib-python"): import cv2 @@ -35,6 +36,7 @@ class DetResizeForTest: def __init__(self, input_shape=None, max_side_limit=4000, **kwargs): self.resize_type = 0 self.keep_ratio = False + self._large_input_warner = LargeDetectorInputWarner() if input_shape is not None: self.input_shape = input_shape self.resize_type = 3 @@ -71,6 +73,8 @@ def __call__( img, shape = self.resize( ori_img, limit_side_len, limit_type, max_side_limit ) + if img is not None: + self._large_input_warner.warn(ori_img.shape, img.shape, logging.warning) resize_imgs.append(img) img_shapes.append(shape) return resize_imgs, img_shapes diff --git a/tests/inference/models/text_detection/test_processors.py b/tests/inference/models/text_detection/test_processors.py new file mode 100644 index 0000000000..495437e968 --- /dev/null +++ b/tests/inference/models/text_detection/test_processors.py @@ -0,0 +1,66 @@ +# Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import importlib.util +from pathlib import Path +from unittest.mock import Mock + + +REPO_ROOT = Path(__file__).resolve().parents[4] +spec = importlib.util.spec_from_file_location( + "large_input_warning", + REPO_ROOT / "paddlex/inference/models/text_detection/_large_input_warning.py", +) +large_input_warning = importlib.util.module_from_spec(spec) +spec.loader.exec_module(large_input_warning) + + +LARGE_DET_INPUT_WARN_PIXELS = large_input_warning.LARGE_DET_INPUT_WARN_PIXELS +LargeDetectorInputWarner = large_input_warning.LargeDetectorInputWarner + + +def test_large_detector_input_warning_boundary(): + warner = LargeDetectorInputWarner() + warning = Mock() + + warner.warn( + (1000, 4000, 3), + (1000, LARGE_DET_INPUT_WARN_PIXELS // 1000, 3), + warning, + ) + + warning.assert_not_called() + + +def test_large_detector_input_warning_is_bounded_per_processor(): + warner = LargeDetectorInputWarner() + warning = Mock() + + warner.warn((3000, 2000, 3), (3000, 2000, 3), warning) + warner.warn((4000, 3000, 3), (4000, 3000, 3), warning) + + warning.assert_called_once() + + +def test_large_detector_input_warning_describes_detector_and_source_paths(): + warner = LargeDetectorInputWarner() + warning = Mock() + + warner.warn((3000, 4000, 3), (2048, 2048, 3), warning) + + message = warning.call_args.args[0] + assert "2048x2048" in message + assert "4000x3000 source image" in message + assert "without downscaling" not in message + assert "text_det_limit" not in message