Сжатие изображений с использованием SVD
В этой демонстрации показано, как работать с цветовыми каналами для изучения сжатия изображений с использованием сингулярного разложения (SVD).
using Images, TestImages
using LinearAlgebra
img = float.(testimage("mandrill"))
channels = channelview(img)
function rank_approx(F::SVD, k)
U, S, V = F
M = U[:, 1:k] * Diagonal(S[1:k]) * V[:, 1:k]'
clamp01!(M)
end
Для каждого канала выполняется разложение SVD, а затем канал реконструируется с использованием только K наибольших сингулярных значений.
Изображение сжимается по той причине, что для каждого канала требуется сохранить лишь две небольшие матрицы и один вектор — усеченную часть (U, S, V)
. Например, если исходное изображение в оттенках серого размером (512, 512)
воссоздается с использованием сингулярных значений, то для его воссоздания необходимо сохранить лишь чисел, в то время как исходное изображение содержит чисел. Следовательно, получается коэффициент сжатия , если не принимать во внимание тип для хранения.
# до версии julia 1.1:
# svdfactors = (svd(channels[1,:,:]), svd(channels[2,:,:]), svd(channels[3,:,:]))
svdfactors = svd.(eachslice(channels; dims=1))
imgs = map((10, 50, 100)) do k
colorview(RGB, rank_approx.(svdfactors, k)...)
end
mosaicview(img, imgs...; nrow=1, npad=10)

Слева направо: исходное изображение, реконструированные изображения с использованием 10, 50 и 100 наибольших сингулярных значений. Мы видим, что наибольших сингулярных значений позволяют достаточно хорошо воссоздать изображение.
Эта страница была создана с помощью DemoCards.jl и Literate.jl.