День 3 Летней школы Julia
Типы и трансформация изображений
Цель данной демонстрации – показать способы задания изображений и базовые принципы их преобразования.
using Images # Библиотека обработки изображений
using ImageShow # Библиотека отрисовки изображений
Типы цветовых пространств
Любое изображение – это просто массив пиксельных объектов. Элементы изображения называются пикселями, а Julia Images рассматривает пиксели как первоклассные объекты. Например, у нас есть Gray-пиксели в оттенках серого, RGB-пиксели цвета, Lab-пиксели цвета.
img_rgb = [RGB(1.0, 0.5, 1.0), RGB(1.0, 1.0, 0.0), RGB(0.5, 0.0, 1.0)]
dump(img_rgb)
img_gray = rand(Gray, 3, 3)
dump(img_gray)
Перевод между типами объектов
Gray.(img_rgb) # RGB => Gray
RGB.(img_gray) # Gray => RGB
Трансформация изображений
Для начала загрузим изображение из файла .jpg.
img = load( "$(@__DIR__)/Resources/img.jpg" )
Увеличим контрастность загруженного изображения.
alg = Equalization(nbins = 256)
img_adjusted = adjust_histogram(img, alg)
Уменьшим размер изображения в четыре раза относительно исходника.
img_small = imresize(img_adjusted, ratio=1/4)
Также imresize позволяет изменять размер с использованием ручного задания размерностей, например:
imresize(img, (400, 400)).
print(size(img_adjusted), " --> ", size(img_small))
Аффинное преобразование – отображение плоскости
или пространства в себя.
Преобразование задаётся матрицей трансформации изображения по принципу, описанному на картинке ниже.

Далее объявим функцию аффинной трансформации изображения, в которой:
- theta – это матрица трансформации;
- img – это входное изображение;
- out_size – размеры выходного изображения;
- grid – решётка пиксельной индексации.
# Вспомогательная функция контроля размерностей
function C_B_V(x, max_val)
x[x .> max_val - 1] .= max_val - 1
x[x .< 1] .= 1
return x
end
function transform(theta, img, out_size)
grid = grid = zeros(3, out_size[1]*out_size[2])
grid[1, :] = reshape(((-1:2/(out_size[1]-1):1)*ones(1,out_size[2])), 1, size(grid,2))
grid[2, :] = reshape((ones(out_size[1],1)*(-1:2/(out_size[2]-1):1)'), 1, size(grid,2))
grid[3, :] = ones(Int, size(grid, 2))
# Умножение theta на grid
T_g = theta * grid
# Вычисление координат x, y
x = (T_g[1, :] .+ 1) .* (out_size[2]) / 2
y = (T_g[2, :] .+ 1) .* (out_size[1]) / 2
# Округление координат
x0 = ceil.(x)
x1 = x0 .+ 1
y0 = ceil.(y)
y1 = y0 .+ 1
# Обрезание значений x0, x1, y0, y1
x0 = C_B_V(x0, out_size[2])
x1 = C_B_V(x1, out_size[2])
y0 = C_B_V(y0, out_size[1])
y1 = C_B_V(y1, out_size[1])
# Вычисление базовых координат
base_y0 = y0 .* out_size[1]
base_y1 = y1 .* out_size[1]
# Работа с изображением
im_flat = reshape(img, :)
# Обрабатываем координаты
A = (x1 .- x) .* (y1 .- y) .* im_flat[Int.(base_y0 .+ x0 .+ 1)]
B = (x1 .- x) .* (y .- y0) .* im_flat[Int.(base_y1 .+ x0 .+ 1)]
C = (x .- x0) .* (y1 .- y) .* im_flat[Int.(base_y0 .+ x1 .+ 1)]
D = (x .- x0) .* (y .- y0) .* im_flat[Int.(base_y1 .+ x1 .+ 1)]
# Расчет результата
result = reshape((A .+ B .+ C .+ D), (out_size[1], out_size[2]))
return result
end
Для начала применим эту функцию к изображению в оттенках серого.
img_sg = Gray.(img_small)
theta = [2 0.3 0; -0.3 2 0]
img_transfor = transform(theta, img_sg, [size(img_sg,1),size(img_sg,2)])
Как мы видим, размер уменьшен в два раза и выполнен поворот.
Для получения обратного преобразования находим обратную
матрицу от матрицы трансформации. Это можно сделать при
помощи функции inv.
Теперь применим данную функцию к изображению формата RGB.
Для начала преобразуем изображения формата RGB к канальному
представлению.
img_CHW = channelview(img_small);
print(size(img_small), " --> ", size(img_CHW))
RGB.(img_CHW[1,:,:], 0.0, 0.0) # red
RGB.(img_CHW[1,:,:], img_CHW[1,:,:], img_CHW[1,:,:]) # Gray
img_CHW_new = zeros(size(img_CHW))
for i in 1:size(img_CHW,1)
img_CHW_new[i,:,:] = transform(theta, img_CHW[i,:,:], [size(img_CHW,2),size(img_CHW,3)])
end
RGB.(img_CHW_new[1,:,:], img_CHW_new[2,:,:], img_CHW_new[3,:,:])
Обработка изображений
В данном примере мы продемонстируем, как применять Engee для обработки изображений, разберём отдельные функции для обработки изображений, рассмотрим возможности обращения к изображениям и методы их обработки и представления.
Обнаружение углов
Обнаружение углов полезно в ряде задач компьютерного зрения — регистрация изображений, обнаружение движения и панорамное сшивание. Метод основан на том, что, если расположение одних и тех же точек известно на двух разных изображениях, это дает возможности для выравнивания этих изображений.
После обнаружения точек интереса отметим их красным цветом, переведя изображения в оттенках серого в RGB и присвоив первому измерению матрицы значения единицы в точках интереса.
img = load( "$(@__DIR__)/Resources/img.jpg" )
corners = imcorner(img, Percentile(98.5));
img_copy = RGB.(img)
img_copy[corners] .= RGB(1.0, 0.0, 0.0)
simshow(img_copy)
Обнаружение границ изображенных объектов
Ещё одной частой задачей при обработке изображений является
нахождение границ объектов. Для этого воспользуемся функцией
Kernel.sobel, которая позволяет перевести изображения в частотную область.
function brightness(pixel)
arr = pixel.r + pixel.g + pixel.b;
return sum(arr) / length(arr)
end
function find_energy(image)
energy_y = imfilter(brightness.(image), Kernel.sobel()[1])
energy_x = imfilter(brightness.(image), Kernel.sobel()[2])
return sqrt.(energy_x.^2 + energy_y.^2)
end
simshow(find_energy(img))
По результатам обработки мы однозначно можем определить границы каждого объекта на изображении, и эти данные впоследствии могут быть применены к дальнейшей обработке изображения.
Игра «Жизнь»
Это клеточный автомат, игра без игроков, в которой пользователь создаёт начальное состояние, а потом лишь наблюдает за её развитием. В игре можно создать процессы с полнотой по Тьюрингу, что позволяет реализовать любую машину Тьюринга.
Правила игры таковы.
- В пустой клетке, с которой соседствуют три живые клетки, зарождается жизнь.
- Eсли у живой клетки есть две или три живые соседки, то эта клетка продолжает жить.
- Если живых соседей меньше двух или больше трёх клетка умирает.
Ссылка: https://engee.com/community/ru/catalogs/projects/igra-zhizn_1










