Документация Engee

Массивы: более сложное индексирование

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

Отслеживание позиции с помощью нетрадиционных индексов

Рассмотрим следующую пару изображений:

imgref img

cameraman

cameraman

Как легко догадаться, изображение справа — это повернутая версия изображения слева. Но на какой угол? Было ли также выполнено преобразование?

«Примитивный» способ проверить это — поворачивать и смещать изображение справа до тех пор, пока оно не совпадет с изображением слева. Мы можем наложить два изображения (Using colorview to make color overlays), чтобы узнать, насколько точно они совпадают.

julia> using Images, CoordinateTransformations, Rotations

julia> tfm = recenter(RotMatrix(pi/8), center(img))
AffineMap([0.9238795325112867 -0.3826834323650898; 0.3826834323650898 0.9238795325112867], [88.77855462171088, -59.31993370357884])

julia> imgrot = warp(img, tfm);

julia> summary(img)
"386×386 Array{Gray{N0f8},2} with eltype Gray{N0f8}"

julia> summary(imgrot)
"506×506 OffsetArray(::Array{Gray{N0f8},2}, -59:446, -59:446) with eltype Gray{N0f8} with indices -59:446×-59:446"

В то время как у img оси, как обычно, начинаются с 1, в сводке по изображению imgrot указано, что оно имеет оси (-59:446, -59:446). Это означает, что первый элемент imgrot имеет индексы imgrot[-59,-59], а последний элемент — индексы imgrot[446,446].

Каков смысл таких индексов, которые выходят за пределы исходного массива в обоих направлениях? Это можно понять при отображении повернутого изображения, особенно если наложить его на исходное:

julia> imgov = colorview(RGB, paddedviews(0, img, imgrot, zeroarray)...)
rot_overlay

Дополнение со всех сторон массива нужно по той причине, что часть пикселей повернутого изображения (зеленого) выходит за пределы области, занимаемой исходным изображением (красным). Из-за того, что в Julia допускаются отрицательные индексы, у нас не возникает проблем с «дополнением» исходного изображения: мы просто копируем оригинал в дополненный массив, используя исходные индексы.

Мы можем проверить, хорошо ли imgrot совпадает с исходным неповернутым изображением imgref, приведенным в начале этой страницы:

julia> imgov_ref = colorview(RGB, paddedviews(0, imgref, imgrot, zeroarray)...)
ref_overlay

Тот факт, что перекрывающаяся часть выглядит желтой (сочетание красного и зеленого), означает, что совпадение идеальное.

Дополнительные сведения о поддержке произвольных индексов в Julia см. в этой записи в блоге.

Отслеживание ориентации с помощью именованных осей

Предположим, у вас есть трехмерное изображение в оттенках серого. Это фильм (двухмерное изображение во времени) или трехмерное изображение (x, y и z)? Для ориентации в таких ситуациях один из лучших способов — присвоить осям имена. В пакете TestImages есть пример файла, иллюстрирующего такую ситуацию:

julia> using Images, TestImages

julia> img = testimage("mri");

julia> println(summary(img))
3-dimensional AxisArray{Gray{N0f8},3,...} with axes:
    :P, 0:1:225
    :R, 0:1:185
    :S, 0:5:130
And data, a 226×186×27 Array{Gray{N0f8},3} with eltype Gray{N0f8}

TestImages использует пакет AxisArrays для присвоения имен осям данного изображения в терминах системы координат RAS (правая, передняя, верхняя), которая обычно применяется в магнитно-резонансной томографии. Дополнительные сведения о создании собственных объектов AxisArray см. в документации к этому пакету.

Эта система координат может упрощать визуализацию. Давайте посмотрим на «горизонтальный срез», перпендикулярный оси «верх-низ» (то есть срез с постоянным значением S):

Sslice

Из сводки видно, что в срезе остались только оси :A и :R.

Можно было бы также выполнить срезы по осям R и A, но для этого изображения (очень анизотропного) они не столь информативны.

Пакеты ImageAxes и ImageMetadata расширяют функциональность AxisArrays и могут быть полезны, когда нужно закодировать больше информации об изображении.