Дымка на изображениях может стать настоящей проблемой, и не всегда для ее удаления нужны сложные алгоритмы или нейронные сети. Я хочу продемонстрировать реализацию метода удаления дымки Robust Single Image Haze Removal Using Dark Channel Prior and Optimal Transmission Map and Adaptive Atmospheric Light (Удаление дымки с использованием метода предварительного темного канала, карты пропускания и не однородного света) в .NET.
Преимущества подхода:
Простота и эффективность: Метод, основанный на интуитивных принципах обработки изображений, легко воспринимается и прост в реализации. Использование только математических операций, и зная их параметры, в итоговом изображении никогда не будут присутствовать неизвестные артефакты или “фантомы”. Работа с изображением не будет выглядеть как копание в черном ящике с параметрами нейронной сети или библиотеки с закрытым алгоритмом.
Отсутствие зависимости от обучающих данных: Не требует сложного обучающего набора данных, что сокращает затраты и упрощает процесс.
Высокая скорость работы: Работает быстро и не требует значительных вычислительных ресурсов.
Прозрачность и интерпретируемость: Легко понимаемый метод обработки изображений, что упрощает объяснение и обоснование результатов.
Универсальность: Хорошо работает на различных типах изображений и условиях освещения без необходимости сложной перенастройки.
Используемые инструменты:
Для решения задачи удаления дымки мы используем библиотеку EmguCV, обертку для OpenCV в .NET. Этот инструмент обеспечивает удобный доступ к широкому спектру функций обработки изображений и видео, и матриц вообще. Причем синтаксис для работы с CPU и GPU примерно одинаковый new Mat() или new GpuMat(). Но есть отличие в вызове методов, которое унаследовано из OpenCV . И при работе с GpuMat требуется более тщательно следить за сборкой мусора, или реализовать свой интерфейс с GC, или придется постоянно использовать using. На github есть issue по очистке памяти GpuMat , но, пока оно не закрыто.
![](https://habrastorage.org/getpro/habr/post_images/985/6b9/42e/9856b942e2062d0f99a72281f1d91b62.jpg)
Схема атмосферного света была любезно предоставлена mirasnowfox
Основные компоненты этого метода включают:
Оценка атмосферного света:
используя квадратное разложение
![](https://habrastorage.org/getpro/habr/post_images/c95/a5c/009/c95a5c009631123571112bcec03e7132.jpg)
выберем область с наибольшей яркостью
![](https://habrastorage.org/getpro/habr/post_images/d77/c3e/289/d77c3e289ddc2a74f6f05bc13baf416d.jpg)
так мы скорее всего избежим посторонние источники света, например, фары машин, и ускорим последующую сортировку. Далее для полученного участка находим его темный канал: простой, но эффективный способ оценить информацию о глубине сцены. Пример реализации
private Mat ComputeDarkChannelPatch(Image<Bgr, float> srcImage, int patch)
{
var bgrChannels = srcImage.Clone().Mat.Split();
var darkChannel = new Mat();
CvInvoke.Min(bgrChannels[0], bgrChannels[1], darkChannel);
CvInvoke.Min(darkChannel, bgrChannels[2], darkChannel);
CvInvoke.Erode(darkChannel, darkChannel, null, new Point(-1, -1), patch, BorderType.Reflect101, default);
return darkChannel;
}
Формула где
,
и
представляют интенсивность красного, зеленого и синего каналов для каждого пикселя соответственно. Сортируем и выбираем некоторый процент наиболее ярких пикселей, затем вычисляем для них среднее значения Ac по каждому каналу RGB.
Построение оптимальной карты трансмиссии:
строим карту трансмиссии
![](https://habrastorage.org/getpro/habr/post_images/615/5df/be1/6155dfbe14fba85dc6ad1f4150760ee4.jpg)
по формуле где коэффициент ослабления атмосферы, которая оптимально отражает степень проникновения света через туман в каждой точке изображения. Хотя есть более простая альтернатива
где
количество дымки для удаления
Уточнение карты трансмиссии:
к полученной карте трансмиссии применим Guided Filter, для
![](https://habrastorage.org/getpro/habr/post_images/c7f/48c/271/c7f48c271f0037bfbe1baab7eca5d5d3.jpg)
для смягчения краев у ярких мест изображения. Это могут быть источники света, места с сильным эффектом дымки, различные отражающие поверхности. Для GPU версии я использовал работу Kaiming He (kahe@microsoft.com) реализация в MATLAB http://research.microsoft.com/en-us/um/people/kahe/eccv10/guided-filter-code-v1.rar
Восстановление изображения:
производится по формуле: где I(x,y) - значение туманного пикселя, J(x,y) - значение безтуманного пикселя.
![](https://habrastorage.org/getpro/habr/post_images/5c4/8d8/e4a/5c48d8e4adfdf4ed9d7006db3dd0beb9.jpg)
Для сравнение изображение перед обработкой
![](https://habrastorage.org/getpro/habr/post_images/7b7/280/378/7b72803789258ab8083feb5fdf123261.jpg)
Применение такого простого метода может значительно улучшить качество изображений и облегчить их последующий анализ и обработку.
Ссылка на проект github