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-пайплайном.

Sources

Related topics