Обнаружение областей на изображении с высокой температурой¶
В этом примере покажем, как можно автоматически обнаруживать объекты с повышенной температурой на изображении. С помощью анализа изображения мы выделим горячие области, а также определим температуру этой области. По своей сути, это иммитирует работу тепловизора.
Подключим необходимые пакеты¶
import Pkg
Pkg.add("Images")
Pkg.add("ColorSchemes")
Pkg.add("ImageDraw")
Pkg.add("OpenCV")
Pkg.add("ImageMorphology")
using Images # Для работы с изображениями
using ColorSchemes # Для применения воспринимаемых цветовых карт
using ImageDraw # Для рисования на изображениях
using OpenCV # Для работы с OpenCV
using ImageMorphology # Для выполнения морфологических операций над изображениями
Загрузим изображение с зажигалкой, на котором видна область с повышенной температурой. С помощью методов обработки изображений мы выделим область высокой температуры, а также оценим температуру этой области.
image = Images.load("$(@__DIR__)/lighter.jpg")
Уменьшим размер изображения для удобства отображения:
image = imresize(image, (550, 712))
Преобразование изображения¶
Переведем изображение в оттенки серого:
image_gray = Gray.(image)
Загрузим цветовую карту, которая используется для визуализации данных с различной интенсивностью. На ней яркие и насыщенные цвета указывают на более высокие значения, а темные — на низкие. В данном примере она будет применена для отображения областей с различными уровнями температуры, улучшая восприятие температурных различий на изображении.
colormap_ = ColorSchemes.hot
Применим цветовую карту к исходному изображению с помощью функции apply_colorscheme
:
function apply_colorscheme(img, colorscheme)
colored_img = [get(colorscheme, pixel) for pixel in img]
return colorview(RGB, reshape(colored_img, size(img)...))
end
inferno_img = apply_colorscheme(image_gray, colormap_)
Бинаризация и морфологические операции¶
Далее будут применяться бинаризация и морфологические операции для выделения объектов с повышенной температурой.
Бинаризация: этот метод преобразует изображение в бинарное (черно-белое). Это помогает выделить только те области, которые имеют интенсивность, соответствующую интересующему нас диапазону.
Морфологические операции: для улучшения результатов бинаризации будут применяться морфологические операции, такие как эрозия и дилатация. Эрозия уменьшает размеры объектов, убирая шум и маленькие детали, тогда как дилатация увеличивает их.
Определим порог бинаризации:
threshold = 240 / 255
Выполним бинаризацию, присваивая логическую едииницу пикселям, превышающим порог интенсивности, а логический ноль всем остальным:
binary_thresh = Gray.(image_gray .> threshold)
Как видно из рисунка выше, на результирующей бинарной маске осталась область с пламенем от зажигалки. Однако есть шумы, которые мы удалим с помощью морфологических операций.
Зададим ядро, необходимое для эрозии и дилатации:
kernel = strel_diamond((9, 9), r=2)
Посмотрим на результат применения морфологических операций:
BWerode = erode(binary_thresh, kernel)
BWdilate = dilate(BWerode, kernel)
Как видно из рисунка выше, у нас осталось четко выделенная область с высокой температурой.
Выделение горячей области в ограничивающий прямоугольник¶
Далее необходимо ограничить интересующую нас область. Для этого применим методы из пакета OpenCV.
Необходимо опять поиграться с форматами изображений. Сначала переведем изображение в RGB формат:
BWdilate = RGB.(BWdilate)
typeof(BWdilate)
Далее представим изображение в формат, с которым может работать OpenCV:
img_bw_raw = collect(rawview(channelview(BWdilate)));
img_gray_CV = OpenCV.cvtColor(img_bw_raw, OpenCV.COLOR_RGB2GRAY);
Теперь наше изображение формата MAT от OpenCV. Далее ищем контуры нашей области:
contours, _ = OpenCV.findContours(img_gray_CV, 1, 2)
Вычислим координаты ограничивающего прямоугольника области и посмотрим, что они собой представляют:
rect = OpenCV.boundingRect(contours[1])
println("Bounding box: x=$(rect.x), y=$(rect.y), width=$(rect.width), height=$(rect.height)")
Визуализируем изображение с ограничивающим прямоугольником¶
img_with_rect = draw(image, Polygon(RectanglePoints(CartesianIndex(rect.y, rect.x), CartesianIndex(rect.y + rect.height, rect.x + rect.width))), RGB{N0f8}(1.0, 0, 0.0))
Определение температуры¶
Далее мы определим температуру выбранной области. Идея заключается в том, чтобы использовать среднее значение яркости пикселей в этой области для вычисления температуры, применяя заранее установленный калибровочный коэффициент.
Опишем функцию, которая учитывает коэффициент калибровки для среднего значения пикселя - convert_to_temperature
:
function convert_to_temperature(pixel_avg, calibration_factor=4.6)
return pixel_avg * calibration_factor
end;
Повторим преобразования для исходного изображения, чтобы с учетом маски посчитать среднее значение области. В данном контексте маска - изображение после морфологических операций. Она позволяет изолировать только ту область, для которой мы хотим вычислить среднее значение интенсивности.
img_raw = collect(rawview(channelview(image)));
img_gray_CV_img = OpenCV.cvtColor(img_raw, OpenCV.COLOR_RGB2GRAY);
Вычислим среднее значение интенсивности по области:
mean_value = OpenCV.mean(img_gray_CV_img, img_gray_CV)[1]
И преобразуем его в температуру. Значения температуры берутся по шкале Цельсия:
println("Температура области:", convert_to_temperature(mean_value))
Выводы¶
В ходе данного примера мы продемонстрировали процесс обнаружения и определения температуры горячей области на изображении с помощью методов обработки изображений. Мы начали с преобразования изображения в подходящий формат, затем использовали бинаризацию для выделения интересующих областей и применили морфологические операции для улучшения результатов. После этого мы вычислили температуру выбранной области, используя маску и калибровочный коэффициент для преобразования яркости пикселей в температуру. Этот процесс, в итоге, позволяет выявлять горячие участки и измерять их температуру, имитируя работу тепловизора и обеспечивая полезную информацию для анализа.