Обнаружение мелких объектов с помощью разбиения изображений на тайлы в Ultralytics YOLO: от Python до Rust
Узнай, когда разбиение изображений на тайлы помогает YOLO обнаруживать мелкие объекты, сравни затраты и запускай встроенный тайловый инференс на Python или Rust без SAHI.
Onuralp Sezer14 мин. чтения
Почему детектор, который хорошо работает на обычных фотографиях, пропускает большинство людей на кадре с дрона? Часто причина в том, что он ни разу не видит их в исходном размере. При стандартном значении imgsz=640 Ultralytics YOLO трижды уменьшает кадр размером 1920 x 1080, прежде чем модель его обработает, поэтому пешеход высотой 15 пикселей становится примерно 5 пикселей.
Разбиение изображений на тайлы помогает сохранить детали мелких объектов: модель обрабатывает перекрывающиеся фрагменты изображения в исходном разрешении, а затем объединяет результаты. На одном кадре VisDrone из нашей документации число обнаружений Ultralytics YOLO26s выросло с 35 до 161. Цена — больше вычислений на кадр: для него нужно обработать восемь тайлов вместо одного изображения.
Разбиение на тайлы теперь встроено в оба компонента развёртывания. В пакете Python аргумент tile появился в Ultralytics 8.4.204 6 ноября, а в крейте Rust флаг --tile добавлен в Ultralytics Inference 0.0.57 9 ноября. В этом руководстве рассказывается, когда разбиение помогает обнаруживать мелкие объекты, сколько оно стоит и как использовать его в каждом варианте.
Из-за уменьшения размера мелкие объекты становятся незаметными#
Обнаруживать мелкие объекты сложно по простой причине: у объекта есть только те пиксели, которые есть. Модель обнаружения объектов учится распознавать формы по нескольким пикселям на объект, а когда весь кадр уменьшается до 640 пикселей по длинной стороне, удалённые люди, транспорт и дефекты становятся слишком мелкими, чтобы сеть могла отличить их от текстур и шума.
Чаще всего это заметно на аэрофотоснимках, при анализе спутниковых изображений, на широкоугольных камерах дорожного движения и видеонаблюдения, а также на фотографиях объектов с высоким разрешением для инспекции. VisDrone — широко используемый общедоступный аэрофотоснимочный бенчмарк: в документации говорится, что объекты на кадре часто занимают всего несколько десятков пикселей и расположены плотными группами, где многие из них сильно перекрываются.
Разбиение на тайлы сохраняет эти пиксели. Если задать tile равным размеру входа модели, модель увидит несколько фрагментов в исходном разрешении вместо одного прохода по уменьшенному кадру. Идея соответствует методу, который в статье SAHI назван инференсом с гиперинференцией на основе нарезки; авторы оценили его на аэрофотоснимочных наборах данных VisDrone и xView.
В руководстве по разбиению изображений высокого разрешения на тайлы показано, что YOLO26s на кадре VisDrone размером 1920 x 1080 при стандартном пороге уверенности выдаёт 35 обнаружений на всём изображении при imgsz=640 и 161 при tile=640, в том числе для удалённых пешеходов, велосипедистов и автомобилей. В руководстве оба изображения показаны рядом. Это число предсказаний, а не результат оценки качества. Для обоих вариантов использовались одинаковые веса; разбиение также изменило контекст, доступный каждому фрагменту.

Второй кадр валидации VisDrone размером 1920 x 1080, YOLO26s при стандартном пороге уверенности: 8 обнаружений на всём кадре при imgsz=640 и 128 при tile=640. Показан фрагмент дороги, рамки без названий классов.
На каждое окно приходится один дополнительный вход модели#
В руководстве точно описан принцип разбиения на окна. Окна перекрываются на 20% от базового значения, а последняя строка и последний столбец выравниваются по границе изображения, поэтому крайние окна могут перекрываться сильнее. Если изображение меньше окна, используется одно окно на всё изображение.
Так затраты легко предсказать. Для кадра размером 1920 x 1080 при tile=640 обрабатываются восемь окон: четыре по горизонтали и два по вертикали. Для кадра размером 3840 x 2160 при tile=1280 тоже обрабатываются восемь окон. Если применить то же правило перекрытия 20% к кадру размером 3840 x 2160 при tile=640, получится восемь столбцов и четыре строки, то есть 32 окна. Таким образом, уменьшение размера окна вдвое для кадра 4K увеличивает число входов-тайлов в четыре раза.

Восемь окон, которые tile=640 использует для кадра размером 1920 x 1080: столбцы начинаются на x = 0, 512, 1024 и 1280, строки — на y = 0 и 440. Затенённые полосы видны более чем в одном окне.
Пакетная обработка определяет, как эти входы поступают в модель. В Python параметр batch задаёт, сколько окон модель обрабатывает вместе за один вызов инференса; в крейте Rust для динамического экспорта с пакетной обработкой используется --batch. Пакетная обработка может повысить пропускную способность, но измерь задержку на своём оборудовании; в нашем руководстве по пакетному инференсу с Ultralytics YOLO объясняется почему.
Вот как разбиение на тайлы сравнивается с другими способами увеличить число пикселей для мелких объектов:
| Подход | Входы модели для кадра размером 1920 x 1080 | Что видит модель | Когда подходит лучше всего |
|---|---|---|---|
Всё изображение, imgsz=640 | 1 | Кадр уменьшен в 3 раза | После изменения размера объекты остаются хорошо различимыми |
Всё изображение, imgsz=1280 | 1, примерно в 4 раза больше вычислений, чем при размере 640 | Кадр уменьшен в 1,5 раза | Объём памяти и задержка позволяют использовать больший размер входа |
tile=True с imgsz=640 | 8 | Окна размером 640 пикселей в исходном разрешении | Изображения в несколько раз больше входного размера модели |
tile=400 с imgsz=640 | Более 8 | Окна увеличены до 640 пикселей | Даже в исходном разрешении объекты имеют ширину всего в несколько пикселей |
Каждый тайл — обычный вход модели, поэтому разбиение позволяет обрабатывать очень большие изображения, не увеличивая imgsz. Для выходных данных в исходном размере, например масок и карт глубины, по-прежнему нужна память, объём которой пропорционален исходному изображению, а max_det ограничивает число сохраняемых масок экземпляров.
Когда разбиение на тайлы помогает, а когда мешает#
Разбиение помогает, если объекты малы относительно кадра, а кадр намного больше входа модели. Подход подходит для аэрофотоснимков и спутниковых изображений, дорожного движения с высоты, толп, широких фотографий торговых полок и изображений для визуальной инспекции целых плат или панелей.
Если объекты крупные, разбиение мешает. В окне видна лишь часть грузовика, занимающего половину кадра, и в руководстве об этом сказано прямо: объекты, размер которых превышает область перекрытия, всё равно могут быть разрезаны, поскольку ни одно окно не показывает их целиком, а объединение не склеивает отдельные фрагменты. Кроме того, теряется глобальный контекст. Это особенно важно для классификации и оценки глубины, когда результаты обработки разных тайлов могут расходиться.
Меньшие окна требуют ещё одного компромисса. Увеличение окна размером 400 пикселей до 640 помогает обнаруживать объекты шириной всего в несколько пикселей, но одновременно увеличивает фоновые помехи, что может привести к ложноположительным результатам. Сравни два или три размера тайлов на собственном валидационном наборе и следи как за точностью, так и за полнотой.
Как тайлы объединяются в один результат#
Для каждого окна модель выдаёт предсказания в координатах окна. Разбиение переносит их обратно в систему координат исходного изображения и возвращает по одному объекту Results на каждое исходное изображение, поэтому нижестоящий код, который читает result.boxes, продолжит работать без изменений.
Из-за перекрытия объект рядом со швом может обнаружиться дважды. Для обнаружения дубликаты подавляются с помощью подавления немаксимумов с настройками iou, agnostic_nms и max_det, поэтому наше руководство по настройке порога IoU для NMS напрямую применимо к результатам разбиения на тайлы. Рамка, обрезанная границей окна, удаляется, если другое окно видит объект целиком, вдали от своих границ, а подходящая сохранённая рамка его перекрывает. Поэтому на шве остаётся более полное предсказание. Если для обрезанной рамки нет более подходящего совпадения, она сохраняется.

Иллюстрация обработки шва при y = 640 в том же кадре. Голубые рамки обрезаны нижней границей окон верхнего ряда, пурпурные рамки получены из окон нижнего ряда, а на правой панели показана более полная рамка, сохранённая для каждого автомобиля после объединения.
Каждая задача Ultralytics YOLO выполняет объединение по-своему:
- Обнаружение, сегментация, оценка позы и OBB возвращают рамки, маски, ключевые точки или повёрнутые рамки в координаты исходного изображения и применяют отбор рамок; для OBB используется повёрнутая NMS.
- Семантическая сегментация объединяет карты классов, при перекрытии окон выбирая тайл, расположенный ближе всего к центру.
- Оценка глубины объединяет перекрывающиеся карты глубины, увеличивая вес ближе к центру каждого тайла.
- Классификация усредняет вероятности тайлов.
Конвейер Python также разбивает на тайлы предсказания YOLO-World, YOLOE, RT-DETR и FastSAM. SAM использует собственный конвейер обработки фрагментов и не поддерживает tile.
Тайловый инференс в Python с аргументом tile#
Для разбиения на тайлы нужна версия Ultralytics 8.4.204 или новее; дополнительные пакеты не требуются. В режиме predict передай tile=True, чтобы использовать imgsz в качестве размера окна, или укажи целое число, чтобы задать размер окна отдельно:
from ultralytics import YOLO
model = YOLO("yolo26s.pt")
# Базовый вариант: один проход по кадру, уменьшенному до 640 пикселей
full = model.predict("intersection.jpg", imgsz=640)
# Тайловый вариант: окна размером 640 пикселей в исходном разрешении, 8 окон в пакете
tiled = model.predict("intersection.jpg", imgsz=640, tile=640, batch=8)
print(len(full[0].boxes), len(tiled[0].boxes))Тот же аргумент работает и в CLI с yolo predict model=yolo26s.pt source=large-image.tif tile=640 imgsz=640 batch=8. Для видео передай stream=True, чтобы ограничить использование памяти. В режиме track трекер запускается один раз для каждого кадра по объединённым предсказаниям.
Разбиение на тайлы полезно не только для предсказаний. Если изображения намного больше imgsz, обучай и валидируй модель с тем же параметром:
- Обучай на тайлах с помощью
model.train(data="aerial.yaml", tile=True, imgsz=640). Аннотации обрезаются по границам каждого окна, экземпляры, для которых осталось менее 10% исходной площади рамки, удаляются, а пустые окна сохраняются в качестве отрицательных примеров. - Валидируй на объединённых результатах с помощью
model.val(data="aerial.yaml", tile=True, imgsz=640). Предсказания объединяются до сравнения с исходными аннотациями, поэтому mAP отражает результат для развёрнутой модели. - Кэшируй большие изображения с помощью
cache="ram", поскольку при перемешивании тайлов во время обучения иначе пришлось бы многократно декодировать одно и то же большое изображение. - Сравнивай с базовым вариантом на всём изображении на той же выборке для валидации, прежде чем оставлять модель с разбиением на тайлы. Другие способы повысить метрики для крошечных объектов смотри в нашем списке рекомендаций по mAP для мелких объектов.
Обучение на тайлах показывает модели объекты в том масштабе, в котором она будет видеть их при тайловом инференсе. В нашем руководстве по набору данных для обнаружения дронов описан полный цикл обучения, разбиения на тайлы и оценки на кадрах 4K.
Экспортированные модели тоже работают с тайлами. Разбиение выполняется в конвейере предсказаний Python, поэтому у модели, экспортированной в ONNX или TensorRT, сохраняется стандартный граф входных данных, а YOLO("yolo26s.onnx").predict(source, tile=640) работает как обычно, включая фиксированный размер экспортируемого пакета и последний неполный пакет.

Набор данных VisDrone на Ultralytics Platform — готовый бенчмарк для проверки размеров тайлов до разметки собственных данных.
Чтобы сначала проверить размеры тайлов на общедоступных данных, начни с набора данных VisDrone на Ultralytics Platform. Чтобы отслеживать запуск с тайлами вместе с базовым вариантом, скопируй команду Local Training из диалога обучения Platform, укажи в project проект Platform базового варианта и добавь tile=True, чтобы передавать туда метрики запуска с тайлами.
Тайловый инференс в Rust с новым флагом --tile#
Ultralytics Inference — наш крейт Rust и CLI для запуска экспортированных моделей ONNX через ONNX Runtime и моделей OpenVINO IR напрямую, без среды выполнения Python во время инференса. Он предназначен для серверов, контейнеров и периферийных устройств с CPU, CUDA, TensorRT, CoreML, OpenVINO и другими провайдерами выполнения. Версия 0.0.57 реализует тот же подход к разбиению на тайлы, что и Python: базовое перекрытие окон на 20%, перенос результатов в координаты исходного изображения и удаление дубликатов отдельно для каждого класса.

Иллюстрация. Дорожная камера с периферийным компьютером — пример развёртывания без Python, для которого предназначен крейт Rust.
Команда проверила тайловые результаты, сравнив их с Ultralytics Python на ONNX Runtime CPU, OpenVINO CPU, GPU и NPU, CUDA и TensorRT для изображений, видео и веб-камер. Поддерживаются модели обнаружения, сегментации, семантической сегментации, оценки глубины, классификации, позы и OBB.
В CLI добавь --tile и укажи размер окна либо передай флаг без значения, чтобы использовать --imgsz. Экспорт модели выполняется один раз в Python; для самого инференса нужен только двоичный файл Rust:
# One-time export in Python: a dynamic-batch ONNX model so several windows run per call
pip install -U "ultralytics[export-base]>=8.4.204"
yolo export model=yolo26s.pt format=onnx dynamic=True
# Install the Rust CLI
cargo install ultralytics-inference
# Tiled inference on a large image: 640-pixel windows, 8 per batch
ultralytics-inference predict --model yolo26s.onnx --source aerial.jpg --tile 640 --batch 8При использовании в качестве библиотеки настрой разбиение на тайлы один раз в InferenceConfig, и каждый вызов predict будет обрабатывать тайлы. with_tile(0) использует размер инференса:
use ultralytics_inference::{InferenceConfig, YOLOModel};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = InferenceConfig::new().with_tile(640);
let mut model = YOLOModel::load_with_config("yolo26s.onnx", config)?;
let results = model.predict("aerial.jpg")?;
if let Some(ref boxes) = results[0].boxes {
println!("{} detections", boxes.len());
}
Ok(())
}Дубликаты рамок в разных окнах удаляются с помощью NMS отдельно для каждого класса при заданном значении --iou. В этом же выпуске значение по умолчанию изменено на 0.5, что соответствует стандартным настройкам предсказаний Ultralytics. По умолчанию разбиение на тайлы отключено, поскольку каждое окно — это дополнительный вход модели. Включай его, когда важны детали, измеряй задержку инференса на целевом устройстве и выбирай подходящего провайдера выполнения; наше сравнение ONNX и TensorRT поможет для оборудования NVIDIA, а в руководстве по NVIDIA Jetson описана настройка на устройстве.
Пользователи SAHI могут перейти на встроенный аргумент tile#
Если ты уже нарезаешь изображения с помощью библиотеки SAHI, встроенный аргумент выполняет ту же задачу непосредственно в Ultralytics — без второго пакета и отдельного формата результатов. Наше руководство по интеграции SAHI теперь считается устаревшим; вместо него используй tile.
Чтобы перенести скрипт SAHI, в основном нужно изменить аргументы:
| SAHI | Встроенное разбиение на тайлы |
|---|---|
AutoDetectionModel.from_pretrained(model_type="ultralytics", ...) | YOLO("yolo26s.pt") |
get_sliced_prediction(image, model, slice_height=256, slice_width=256, ...) | model.predict(image, tile=256) |
overlap_height_ratio, overlap_width_ratio | Фиксированное базовое перекрытие 20%, крайние окна выровнены по границам изображения |
PredictionResult SAHI | Стандартный Results Ultralytics |
Окна квадратные, а правила перекрытия и объединения описаны выше и отличаются от настраиваемой постобработки SAHI. Поэтому результаты будут похожими, но не идентичными. После перехода заново проверь пороги на валидационном наборе.
Главное практическое отличие — интеграция. tile поддерживается в обучении, валидации, предсказаниях и трекинге Ultralytics с использованием одного и того же аргумента, возвращает стандартные объекты Results и имеет соответствующий параметр в крейте Rust. Поэтому размер тайла, проверенный в ноутбуке, можно использовать и в двоичном файле Rust на периферийном устройстве.
Кому стоит включить разбиение на тайлы#
Включай разбиение, если запускаешь Ultralytics YOLO на изображениях, которые в несколько раз больше входа модели, и валидация показывает, что мелкие объекты пропускаются. Это подходит для команд, работающих с данными с дронов и спутников, для интеграторов систем дорожного движения и видеонаблюдения с широкоугольными камерами, а также для команд, которые снимают целые платы, панели или полки. Пользователи Rust получают тот же подход к разбиению на тайлы на периферийном оборудовании без среды выполнения Python.
Оставь разбиение выключенным, если объекты велики относительно кадра, если увеличение imgsz уже позволяет обнаруживать их за один проход или если бюджет задержки не позволяет обрабатывать несколько входов-тайлов на кадр. В любом случае сравни результаты с тайлами и всего изображения на одной и той же выборке для валидации при одинаковом пороге уверенности, оценивая полноту, ложноположительные результаты и задержку. Используй разбиение только там, где выигрыш оправдывает дополнительные вычисления.
Ultralytics Platform позволяет хранить это сравнение в одном месте: размечай собственные изображения высокого разрешения или начни с VisDrone, обучи базовую модель на всём изображении на облачных GPU, обучи ещё один базовый вариант с увеличенным imgsz и записывай метрики запуска с тайлами со своего компьютера в тот же проект. В руководстве по разбиению изображений высокого разрешения на тайлы описаны параметры разбиения, а в документации Ultralytics Inference — развёртывание на Rust.
Пакет Python и крейт Rust распространяются по лицензии AGPL-3.0. Если ты планируешь использовать обнаружение с разбиением на тайлы в продукте с закрытым исходным кодом или периферийном устройстве, которое поставляется заказчикам, коммерческая лицензия Ultralytics Enterprise разрешает коммерческое использование охватываемого ею программного обеспечения Ultralytics без обязательств по раскрытию исходного кода согласно AGPL-3.0, в соответствии с её условиями.
Часто задаваемые вопросы
Разбиение изображений на тайлы — это разделение большого изображения на перекрывающиеся окна, запуск детектора на каждом окне и объединение рамок на исходном изображении. Если размер окна совпадает с размером входа модели, мелкие объекты сохраняют пиксели, которые потеряли бы при уменьшении всего изображения. В Ultralytics YOLO аргумент
tileделает это с базовым перекрытием 20% и возвращает один результат на изображение.Сначала проверь, не связано ли это с уменьшением изображения: если объекты при
imgsz=640становятся размером всего в несколько пикселей, попробуй увеличитьimgszилиtile=True. Обучай модель с теми же настройками, которые будешь использовать для предсказаний, чтобы она училась распознавать объекты в масштабе, соответствующем развёртыванию, и валидируй результаты отдельно для каждого размера и класса. Разбиение на тайлы подходит для изображений, которые в несколько раз больше входа модели.На каждое окно приходится один вход модели: для кадра размером 1920 x 1080 при
tile=640вместо одного изображения формируется восемь входов-тайлов. Обработка нескольких тайлов одним пакетным вызовом — с параметромbatchв Python или--batchс экспортом для динамической пакетной обработки в Rust — может повысить пропускную способность. Измерь задержку на целевом оборудовании.Нет. Начиная с Ultralytics 8.4.204 встроенный аргумент
tileвыполняет инференс с нарезкой без дополнительного пакета, а также разбивает на тайлы данные для обучения, валидации и трекинга. Руководство по SAHI в нашей документации устарело; вместо него используйtile.Да. В Python у экспортированных моделей сохраняется стандартный граф входных данных, а
tileпередаётся вpredictкак обычно. В Rust версия Ultralytics Inference 0.0.57 добавляет--tileв CLI иwith_tileвInferenceConfig; работу проверили сравнением с Python на ONNX Runtime CPU, OpenVINO, CUDA и TensorRT.Начни с
tile=True, в которомimgszиспользуется как размер окна. Используй окно поменьше, напримерtile=400сimgsz=640, если объекты занимают всего несколько пикселей даже при исходном разрешении, и побольше, если объекты могут обрезаться на стыках. Сравни несколько размеров на валидационной выборке, обращая внимание и на полноту, и на ложноположительные срабатывания.
Автор
Комментарии
Задай вопрос, поделись результатами или помоги кому-нибудь.










