Как нормализовать изображение?

Нормализация изображения — это процесс приведения пиксельных значений изображения к заданному диапазону или распределению, с целью повышения качества обработки, обучения моделей машинного обучения, улучшения визуального восприятия или повышения устойчивости алгоритмов.

Существует несколько способов нормализации, каждый из которых применяется в зависимости от задачи. Ниже подробно описаны основные подходы, примеры и объяснение, как они работают.

Зачем нужна нормализация изображения?

  1. Стабильность при обучении моделей — многие алгоритмы машинного обучения чувствительны к масштабу входных данных.

  2. Ускорение сходимости — при нормализованных данных градиенты лучше себя ведут.

  3. Сравнение изображений — можно объективно сравнивать изображения по их структуре.

  4. Устранение лишней информации — удаление смещения, освещённости и других артефактов.

Основные типы нормализации

1. Min-Max нормализация (масштабирование в диапазон [0,1] или [-1,1])

Формула:

x' = (x - min) / (max - min)

Если нужно масштабировать к диапазону [−1,1][-1, 1]:

x' = 2 * (x - min) / (max - min) - 1

Пример:
Если у вас изображение в диапазоне [0, 255], то:

normalized = image / 255.0

Это особенно полезно при работе с нейросетями, где входное распределение данных желательно в [0,1] или [-1,1].

2. Z-нормализация (стандартизация)

Формула:

x' = (x - μ) / σ

  • μμ — среднее значение всех пикселей

  • σσ — стандартное отклонение

Используется для приведения изображения к нулевому среднему и единичному стандартному отклонению.

Пример на NumPy:

normalized = (image - image.mean()) / image.std()

Применение: часто используется в сверточных нейросетях и при обучении на наборе изображений, когда требуется одинаковое распределение признаков.

3. Channel-wise Normalization (по каналам RGB)

Если изображение цветное (RGB), может быть полезно нормализовать каждый канал отдельно:

for c in range(3): # для RGB
image\[:, :, c\] = (image\[:, :, c\] - mean\[c\]) / std\[c\]

Часто используется в PyTorch, где задаются заранее известные значения mean и std для датасета (например, ImageNet):

mean = \[0.485, 0.456, 0.406\]
std = \[0.229, 0.224, 0.225\]

Зачем: чтобы модель видела изображения в таком виде, к какому она привыкла при обучении.

4. Histogram Normalization (выравнивание гистограммы)

Это метод растяжения гистограммы изображения для улучшения контраста.

Формула:

x' = (x - min) * (new_max - new_min) / (max - min) + new_min

Обычно применяется на изображениях с плохой освещённостью.

Пример (OpenCV):

img_yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
img_yuv\[:, :, 0\] = cv2.equalizeHist(img_yuv\[:, :, 0\])
normalized = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)

5. CLAHE (Contrast Limited Adaptive Histogram Equalization)

Это локализованная версия гистограммного выравнивания — изображение делится на участки, и на каждом применяется выравнивание с ограничением по усилению контраста.

Пример (OpenCV):

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
normalized = clahe.apply(gray)

6. Логарифмическая и гамма-коррекция

Они трансформируют яркость изображения для усиления деталей.

Гамма-коррекция:

```python
x' = x^γ
При γ < 1 изображение становится ярче, при γ > 1 — темнее.

gamma = 0.5
look_up = np.array([((i / 255.0) ** gamma) * 255 for i in np.arange(0, 256)]).astype("uint8")
normalized = cv2.LUT(image, look_up)

**Логарифмическая трансформация:  
**Подходит для изображений с большим динамическим диапазоном.  
<br/>```python
c = 255 / np.log(1 + np.max(image))
normalized = c \* np.log(1 + image)
normalized = np.array(normalized, dtype=np.uint8)  

7. Локальная нормализация (Local Contrast Normalization)

Это метод, при котором каждый пиксель вычитается из среднего по окрестности, делённого на стандартное отклонение по окрестности.

Формула:

x'(i, j) = (x(i, j) - μ(i, j)) / σ(i, j)

Реализуется при помощи свёртки и используется для устранения локальных артефактов освещения.

8. Бинаризация как частный случай нормализации

Когда изображение приводится к двум значениям (0 и 1), это тоже можно рассматривать как нормализацию:

\_, binary = cv2.threshold(image, thresh=127, maxval=255, type=cv2.THRESH_BINARY)

Полезна для OCR, выделения объектов, анализа контуров.

Какую нормализацию выбрать?

Задача Подходящая нормализация
Подготовка к CNN Channel-wise Z-нормализация (mean/std)
--- ---
Улучшение визуального качества CLAHE, гистограммное выравнивание
--- ---
Обработка в классических алгоритмах (SVM, PCA) Z-нормализация или Min-Max
--- ---
Для сравнения структур Локальная нормализация
--- ---
Сильные перепады яркости Логарифмическая или гамма-коррекция
--- ---

Особенности при использовании библиотек

OpenCV:

  • Работает с изображениями в формате uint8 или float32

  • Некоторые функции (например, cv2.equalizeHist) работают только с grayscale

PIL:

  • Требуется преобразование в массив NumPy для сложных операций

  • Занимается больше визуализацией и простыми трансформациями

NumPy:

  • Универсальный способ работы с изображениями при помощи массивов

PyTorch:

  • Часто используется transforms.Normalize(mean, std)

  • Требует изображения в формате float32, нормализованные в [0,1] до стандартизации

Практический пример на PyTorch

import torchvision.transforms as transforms
transform = transforms.Compose(\[
transforms.ToTensor(), # Преобразование из \[0,255\] в \[0.0,1.0\]
transforms.Normalize(mean=\[0.485, 0.456, 0.406\],
std=\[0.229, 0.224, 0.225\])
\])

Этот подход приводит изображение к распределению, аналогичному обучающему набору ImageNet.

Таким образом, нормализация изображения — это ключевая операция, необходимая для подготовки, анализа и машинной обработки изображений. Каждый метод нормализации имеет свои особенности, применимость и цели, и выбор зависит от контекста задачи.