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

Дескриптор ORB

Дескриптор ORB (Oriented Fast and Rotated Brief, направленный FAST и повернутый BRIEF) несколько похож на BRIEF. У него нет специального шаблона выборки, как у BRISK или FREAK.

Однако между ORB и BRIEF есть два основных различия:

  • ORB использует механизм компенсации ориентации, что делает его инвариантным к повороту.

  • ORB изучает оптимальные пары выборки, тогда как BRIEF использует случайно выбранные пары.

В качестве меры ориентации дескриптор ORB использует центроид интенсивности. Чтобы вычислить этот центроид, сначала нужно найти момент участка, который определяется как Mpq = x,yxpyqI(x,y). Тогда центроид, или «центр масс», определяется как C=(M10M00, M01M00).

Вектор из центра угла к центроиду задает ориентацию участка. Теперь перед вычислением дескриптора участок можно повернуть в некоторую предварительно определенную каноническую ориентацию, чтобы обеспечить инвариантность к повороту.

Алгоритм ORB пытается выбрать некоррелированные пары выборки, чтобы каждая новая пара привносила новую информацию в дескриптор и он в итоге нес в себе максимальный объем информации. Также желательно, чтобы между парами была высокая дисперсия, чтобы признак был более дискриминативным, так как он по-разному реагирует на входные данные. Для этого рассматриваются пары выборки по ключевым точкам в стандартных наборах данных, а затем выполняется жадная оценка всех пар в порядке удаления от среднего значения до тех пор, пока не будет получено требуемое количество пар, то есть размер дескриптора.

Дескриптор строится с использованием сравнений интенсивности пар. Для каждой пары, если первая точка имеет большую интенсивность, чем вторая, то в соответствующий бит дескриптора записывается значение 1; в противном случае записывается 0.

Пример

Давайте рассмотрим простой пример, в котором дескриптор ORB используется для сопоставления двух изображений, одно из которых было смещено на (50, 40) пикселей, а затем повернуто на угол 75 градусов. В этом примере используется изображение cameraman из пакета TestImages.

Сначала создадим два изображения, которые будут сопоставляться с помощью ORB.

using ImageFeatures, TestImages, Images, ImageDraw, CoordinateTransformations, Rotations

img = testimage("cameraman")
img1 = Gray.(img)
rot = recenter(RotMatrix(5pi/6), [size(img1)...] .÷ 2)  # поворот вокруг центра
tform = rot ∘ Translation(-50, -40)
img2 = warp(img1, tform, axes(img1))
ojzyjgx

Дескриптор ORB, в отличие от BRIEF, вычисляет как ключевые точки, так и дескриптор. Чтобы создать дескриптор ORB, сначала нужно определить параметры, вызвав конструктор ORB.

orb_params = ORB(num_keypoints = 1000)
ORB(1000, 12, 0.25, 0.04, 1.3, 8, 1.2)

Теперь передайте изображение с параметрами в функцию create_descriptor.

desc_1, ret_keypoints_1 = create_descriptor(img1, orb_params)
desc_2, ret_keypoints_2 = create_descriptor(img2, orb_params)
(BitVector[[0, 0, 0, 0, 1, 1, 0, 0, 0, 0  …  1, 0, 1, 0, 0, 0, 1, 1, 0, 1], [0, 1, 0, 0, 1, 1, 0, 0, 0, 1  …  1, 0, 1, 1, 0, 0, 1, 1, 0, 1], [0, 1, 1, 0, 0, 1, 1, 0, 0, 0  …  1, 1, 0, 1, 1, 0, 0, 1, 1, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0, 0  …  1, 1, 0, 1, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 1  …  1, 0, 1, 1, 0, 0, 1, 1, 0, 1], [1, 0, 1, 1, 0, 0, 1, 0, 1, 1  …  1, 1, 1, 0, 0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1, 1, 0, 0, 0  …  1, 0, 0, 1, 1, 0, 0, 1, 1, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0, 0  …  1, 0, 0, 1, 0, 1, 1, 0, 0, 1], [0, 1, 0, 0, 1, 0, 1, 0, 1, 0  …  0, 0, 0, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 1, 0, 0, 0  …  0, 0, 1, 1, 0, 1, 1, 0, 1, 0]  …  [0, 0, 0, 0, 0, 0, 1, 0, 1, 1  …  1, 1, 1, 0, 0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 0, 1, 0  …  1, 0, 0, 1, 0, 1, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1, 1, 1, 1, 0  …  0, 0, 1, 1, 0, 0, 0, 1, 0, 0], [0, 1, 1, 1, 0, 0, 0, 1, 0, 1  …  0, 1, 1, 1, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 1, 1, 0  …  1, 1, 1, 1, 0, 1, 1, 0, 1, 1], [0, 1, 1, 0, 0, 0, 1, 1, 1, 0  …  0, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 1, 1, 1, 1, 0, 0, 0  …  1, 1, 0, 1, 0, 0, 0, 1, 0, 0], [1, 1, 0, 0, 0, 1, 1, 0, 1, 0  …  0, 1, 0, 0, 0, 1, 1, 0, 0, 1], [1, 0, 0, 1, 1, 0, 0, 0, 0, 1  …  0, 0, 1, 0, 1, 1, 0, 0, 0, 1], [1, 1, 0, 0, 1, 0, 0, 1, 1, 1  …  0, 0, 1, 1, 1, 1, 1, 0, 0, 0]], CartesianIndex{2}[CartesianIndex(160, 37), CartesianIndex(161, 37), CartesianIndex(336, 296), CartesianIndex(382, 299), CartesianIndex(161, 38), CartesianIndex(158, 242), CartesianIndex(336, 295), CartesianIndex(382, 300), CartesianIndex(150, 241), CartesianIndex(196, 298)  …  CartesianIndex(122, 235), CartesianIndex(248, 273), CartesianIndex(227, 162), CartesianIndex(365, 347), CartesianIndex(234, 184), CartesianIndex(263, 265), CartesianIndex(258, 262), CartesianIndex(164, 247), CartesianIndex(277, 283), CartesianIndex(275, 287)], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0  …  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])

Полученные дескрипторы можно использовать для поиска соответствий между двумя изображениями с помощью функции match_keypoints.

matches = match_keypoints(ret_keypoints_1, ret_keypoints_2, desc_1, desc_2, 0.2)
122-element Vector{Vector{CartesianIndex{2}}}:
 [CartesianIndex(230, 271), CartesianIndex(337, 296)]
 [CartesianIndex(189, 291), CartesianIndex(382, 300)]
 [CartesianIndex(230, 272), CartesianIndex(337, 295)]
 [CartesianIndex(146, 315), CartesianIndex(432, 301)]
 [CartesianIndex(147, 314), CartesianIndex(431, 301)]
 [CartesianIndex(230, 275), CartesianIndex(338, 294)]
 [CartesianIndex(172, 209), CartesianIndex(355, 380)]
 [CartesianIndex(199, 287), CartesianIndex(371, 299)]
 [CartesianIndex(229, 271), CartesianIndex(338, 296)]
 [CartesianIndex(199, 286), CartesianIndex(370, 299)]
 ⋮
 [CartesianIndex(136, 283), CartesianIndex(425, 333)]
 [CartesianIndex(343, 239), CartesianIndex(254, 279)]
 [CartesianIndex(145, 201), CartesianIndex(374, 400)]
 [CartesianIndex(182, 236), CartesianIndex(360, 351)]
 [CartesianIndex(179, 240), CartesianIndex(364, 348)]
 [CartesianIndex(240, 259), CartesianIndex(322, 302)]
 [CartesianIndex(162, 289), CartesianIndex(404, 315)]
 [CartesianIndex(180, 239), CartesianIndex(363, 349)]
 [CartesianIndex(278, 251), CartesianIndex(287, 291)]

Просмотреть результаты можно с помощью пакета ImageDraw.jl.

grid = hcat(img1, img2)
offset = CartesianIndex(0, size(img1, 2))
map(m -> draw!(grid, LineSegment(m[1], m[2] + offset)), matches)
grid
rpqxfhb

Эта страница была создана с помощью DemoCards.jl и Literate.jl.