5.12. Бинарная пороговая обработка¶
Множество конвейеров обработки изображений сводится к вопросу о каждом пикселе: находится ли эта яркость внутри диапазона, который означает «передний план»? Достаточно ли этот цвет близок к красному, чтобы быть маркером, который отслеживает приложение? Является ли этот пиксель частью набора кандидатов, на который должен смотреть следующий этап конвейера? Пороговая обработка – это операция, которая превращает эти вопросы в бинарный ответ в каждой позиции – включено, если пиксель соответствует, выключено, если нет, – и сводит всё изображение к маске, с которой может работать остальная часть конвейера.
5.12.1. Метод binary¶
Метод binary() выполняет эту классификацию по каждому пикселю одним вызовом. Он принимает список диапазонов порогов – условий, которым может соответствовать пиксель, чтобы считаться «включённым», – и переписывает изображение так, что каждый пиксель, соответствующий хотя бы одному из диапазонов, устанавливается в максимальное значение формата, а каждый, который не соответствует, устанавливается в нуль. Результат – это бинарная маска, которую остальная часть конвейера может использовать напрямую.
В простейшей форме список порогов содержит один диапазон, и вызов возвращает маску пикселей в этом диапазоне:
img.binary([(120, 255)])
Именно форма списка делает binary мощным. Конвейер, который хочет отслеживать два цветных маркера или диапазон яркости плюс изолированный пик насыщенности, передаёт оба диапазона в одном списке и получает единую выходную маску, охватывающую все совпадения.
Пороговая обработка превращает изображение с непрерывными значениями в бинарную маску: каждый пиксель внутри диапазона порога становится максимумом формата, каждый пиксель снаружи становится нулём.¶
5.12.2. Кортеж для оттенков серого¶
Для изображения в оттенках серого каждая запись в списке порогов – это кортеж из двух элементов (lo, hi), описывающий включающий диапазон яркости. Пиксели со значениями между lo и hi (включительно) совпадают; всё за пределами этого диапазона – нет. Естественные шаблоны просты:
(0, 60)совпадает с тёмными пикселями – от чёрного до тёмно-серого.(180, 255)совпадает с яркими пикселями – от светло-серого до белого.(100, 160)совпадает с пикселями среднего серого – полоса в середине диапазона яркости.
Порядок двух значений внутри кортежа не имеет значения; метод меняет их местами внутренне, если lo больше hi, поэтому (60, 0) работает так же, как (0, 60).
5.12.3. Кортеж LAB для цвета¶
Для изображения RGB565 каждая запись – это кортеж из шести элементов (l_lo, l_hi, a_lo, a_hi, b_lo, b_hi), описывающий включающий диапазон в цветовом пространстве LAB, а не напрямую в красном, зелёном и синем. Пороги – это L (светлота), A (хроматическая ось от зелёного к красному) и B (хроматическая ось от синего к жёлтому), каждый из которых сравнивается со значением пикселя в этом канале.
Причина использования LAB вместо прямой пороговой обработки RGB – это свойство, ради которого было разработано цветовое пространство LAB: LAB отделяет светлоту от цветности. Два пикселя, которые показывают один и тот же цвет, но при разной яркости, оказываются с разными значениями L, но примерно с одинаковыми значениями A и B. Это разделение позволяет диапазонам порогов описывать цвет по его положению на осях A и B и оставлять диапазон L широко открытым, чтобы принимать этот цвет при любой яркости от тени до света. Порог на основе RGB этого сделать не может – любое изменение освещения сдвигает все три значения R, G, B одновременно, и трекер, построенный на порогах RGB, ломается в первый же раз, когда облако проходит мимо солнца.
Практический шаблон: выбрать диапазоны A и B, описывающие цвет, который отслеживает приложение, и оставить диапазон L широким – часто (0, 100), чтобы принимать любую яркость, – если только приложению специально не нужно применять порог к яркости наряду с цветом.
Для кортежей с менее чем шестью значениями отсутствующие компоненты по умолчанию принимают максимальный диапазон (без ограничения по этой оси). Поэтому кортеж из двух элементов (l_lo, l_hi) в списке порогов RGB565 применяет порог только к светлоте и совпадает с любым цветом.
Примечание
По-настоящему широко открытый диапазон L имеет подвох на нижнем конце. По мере падения светлоты к нулю каждый цвет сходится к чёрному, при этом значения A и B стремятся к нулю и становятся подвержены доминированию шума – поэтому тёмные пиксели могут попасть в диапазоны A и B и отслеживаться как целевой цвет. Если чёрные области сцены загораются как совпадения, поднимайте l_lo, пока они не выпадут.
5.12.4. Флаги¶
Три именованных аргумента управляют выводом:
invert=Trueинвертирует результат. Каждый пиксель, который совпал бы, становится нулём, а каждый пиксель, который был бы нулём, становится максимальным значением. Полезно, когда естественный способ описать передний план – через то, чем он не является.zero=Trueменяет режим работы: совпадающие пиксели обнуляются, а несовпадающие пиксели сохраняют свои исходные значения. Используйте это, когда цель – стереть совпадающие пиксели из изображения, а не свести изображение к их бинарной маске.to_bitmap=Trueвозвращает результат как изображениеBINARYвместо перезаписи существующего формата источника. Результат с одним битом на пиксель – это то, что последующие аргументы маски принимают напрямую, и преобразование часто экономит память, избавляя от необходимости носить с собой маску полного формата.
Маска и ROI следуют той же конвенции, что и остальной интерфейс: прямоугольник roi ограничивает операцию подобластью, а изображение mask ограничивает её произвольным набором позиций.
5.12.5. По умолчанию на месте¶
Как и арифметические операции, binary по умолчанию выполняется на месте: пиксели исходного изображения перезаписываются бинарным выводом, и исходные значения теряются после вызова. Форма to_bitmap=True – это альтернатива, когда источник нужно сохранить, а вывод должен быть свежевыделенным изображением BINARY. Форма copy=True также принимается для результата в том же формате в новом буфере.