OpenCVJuniorCoding
Что такое пороговая обработка (thresholding) в OpenCV и каковы её типы (binary, Otsu, adaptive)?
Thresholding преобразует градации серого в бинарное изображение. cv2.threshold() реализует глобальные методы (binary, Otsu), cv2.adaptiveThreshold() — локальные (mean, Gaussian) для неравномерного освещения.
Что такое пороговая обработка
Пороговая обработка (thresholding) — преобразование изображения в оттенках серого в бинарное (чёрно-белое) изображение путём сравнения каждого пикселя с пороговым значением. Используется для выделения объектов, подготовки масок, OCR и сегментации. В OpenCV за это отвечают две функции: cv2.threshold() и cv2.adaptiveThreshold().
Глобальные методы — cv2.threshold()
Единственный порог применяется ко всему изображению:
- cv2.THRESH_BINARY — пиксель > thresh → maxval, иначе 0.
- cv2.THRESH_BINARY_INV — инверсия предыдущего.
- cv2.THRESH_TRUNC — пиксель > thresh → thresh, иначе оставить.
- cv2.THRESH_TOZERO — пиксель ≤ thresh → 0, иначе оставить.
- cv2.THRESH_OTSU — автоматический подбор порога методом Оцу (межклассовая дисперсия максимальна). Передаётся как флаг совместно с другим:
cv2.THRESH_BINARY + cv2.THRESH_OTSU. Значение thresh в этом случае игнорируется — OpenCV вычисляет его сам.
Адаптивный порог — cv2.adaptiveThreshold()
Для каждого пикселя порог вычисляется локально в окне blockSize × blockSize. Решает проблему неравномерного освещения:
- cv2.ADAPTIVE_THRESH_MEAN_C — порог = среднее окна минус константа C.
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C — порог = взвешенное среднее (гауссово ядро) минус C. Лучше подавляет шум.
Пример кода
import cv2
import numpy as np
img = cv2.imread("document.png", cv2.IMREAD_GRAYSCALE)
if img is None:
raise FileNotFoundError("document.png not found")
# 1. Простой бинарный порог
_, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
cv2.imwrite("out_binary.png", binary)
# 2. Метод Оцу — автоматический порог
otsu_thresh, otsu = cv2.threshold(
img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU
)
print(f"Оцу выбрал порог: {otsu_thresh}")
cv2.imwrite("out_otsu.png", otsu)
# 3. Адаптивный порог (Mean)
adaptive_mean = cv2.adaptiveThreshold(
img,
255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY,
blockSize=11, # нечётное число, > 1
C=2 # вычитаемая константа
)
cv2.imwrite("out_adaptive_mean.png", adaptive_mean)
# 4. Адаптивный порог (Gaussian) — рекомендуется
adaptive_gauss = cv2.adaptiveThreshold(
img,
255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,
blockSize=11,
C=2
)
cv2.imwrite("out_adaptive_gauss.png", adaptive_gauss)
# Перед Оцу полезно размыть изображение:
blurred = cv2.GaussianBlur(img, (5, 5), 0)
_, otsu_blur = cv2.threshold(
blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU
)
cv2.imwrite("out_otsu_blur.png", otsu_blur)
Когда что использовать
- Равномерное освещение, контрастный объект →
THRESH_BINARYс ручным порогом илиTHRESH_OTSU. - Документы, сканы с тенями →
ADAPTIVE_THRESH_GAUSSIAN_C. - Биомедицинские изображения с переменным фоном → адаптивный порог с подобранным blockSize.
- Быстрое прототипирование → Оцу, т.к. не требует ручного подбора порога.
Подводные камни
- Оцу плохо работает на многомодальных гистограммах — если объектов несколько типов яркости, метод даёт субоптимальный порог.
- blockSize должен быть нечётным и >1 — при чётном значении OpenCV выбросит исключение.
- Константа C может быть отрицательной — если фон ярче объекта, C со знаком минус сдвигает порог вверх.
- Шум усиливается адаптивным порогом — без предварительного размытия (
GaussianBlur) адаптивный метод выделяет каждую шумовую крапинку. - Изображение должно быть grayscale — передача BGR-изображения в threshold даёт либо ошибку, либо неожиданный результат.
- THRESH_OTSU игнорирует переданный порог — разработчики иногда передают 127 и удивляются, почему результат другой; правильно передавать 0.
- Малый blockSize даёт шум, большой — теряет детали — выбирайте blockSize ≈ размер наименьшей значимой детали изображения.
- Адаптивный порог медленнее глобального — при обработке видео в реальном времени профилируйте; иногда быстрее обесцветить + Оцу.
Common mistakes
- Объяснять
thresholding methodsтолько синтаксисом без shape, dtype, состояния или режима выполнения. - Игнорировать leakage, воспроизводимость, пустые входы и скрытые копии данных.
- Не проверять production-симптомы: latency, память, ретраи, дрейф качества и несовпадение версий.
What the interviewer is testing
- Может ли связать
thresholding methodsс реальным контрактом входов и выходов. - Упоминает ли тесты, метрики, reproducibility и диагностику ошибок.
- Видит ли различие между demo-кодом в ноутбуке и production-пайплайном.