Новые методы «особых точек» (features) на изображении и LightGlue

"Особые точки", особенности или features используются в компьютерном зрении достаточно давно, в том числе и в OpenCV, в котором  они первоначально были представлены алгоритмом SURF. Алгоритм был тяжеловесный, использующий матрицу Гессе и по началу был в свободном доступе вместе с OpenCV, а потом оказалось, что его лицензия ограничена и начали встраиваться другие алгоритмы, в том числе SIFT, который популярен до сих пор.

Назначение особых точек: сопоставление точек на изображениях для определения поворота объекта и 3D реконструкции.

2024-04-18_17-55-28

Наиболее популярные особенности на настоящий момент:

При этом точность ALIKED при изменении масштаба и поворота значительно выше:

2024-04-18_18-03-46

Данные особые точки использует проект LightGlue:

https://github.com/cvg/LightGlue

LightGlue - легкое средство сопоставления особенностей с высокой точностью и  быстрым выводом. Он принимает на вход набор ключевых точек и дескрипторов для каждого изображения и возвращает индексы соответствующих точек.

Установка:

!git clone https://github.com/cvg/LightGlue.git 

%cd LightGlue

!python -m pip install -e .

Инициализация:

from lightglue import LightGlue, SuperPoint, DISK,ALIKED

from lightglue.utils import load_image, rbd

from lightglue import viz2d

import torch

 

torch.set_grad_enabled(False)

 

device = torch.device("cuda" if torch.cuda.is_available() else "cpu"# 'mps', 'cpu'

 

extractor = SuperPoint(max_num_keypoints=2048).eval().to(device)  # load the extractor

matcher = LightGlue(features="superpoint").eval().to(device)

Скачиваем фото Эрмитажа:

!wget https://cdn.tripster.ru/thumbs2/445d1fbe-1524-11eb-bd4f-9a1addf271b5.800x600.jpg

!wget https://xn--c1acndtdamdoc1ib.xn--p1ai/upload/iblock/115/IMG_6391.jpg

Находим особые точки и ищем совпадения:

imname1 = "445d1fbe-1524-11eb-bd4f-9a1addf271b5.800x600.jpg"

imname2 = "IMG_6391.jpg"

image0 = load_image(imname1)

image1 = load_image(imname2)

 

feats0 = extractor.extract(image0.to(device))

feats1 = extractor.extract(image1.to(device))

matches01 = matcher({"image0": feats0, "image1": feats1})

feats0, feats1, matches01 = [

    rbd(x) for x in [feats0, feats1, matches01]

# remove batch dimension

 

kpts0, kpts1, matches = feats0["keypoints"], feats1["keypoints"], matches01["matches"]

m_kpts0, m_kpts1 = kpts0[matches[..., 0]], kpts1[matches[..., 1]]

 

axes = viz2d.plot_images([image0, image1])

viz2d.plot_matches(m_kpts0, m_kpts1, color="lime", lw=0.2)

viz2d.add_text(0, f'Stop after {matches01["stop"]} layers', fs=20)

 

kpc0, kpc1 = viz2d.cm_prune(matches01["prune0"]), viz2d.cm_prune(matches01["prune1"])

viz2d.plot_images([image0, image1])

 

viz2d.plot_keypoints([kpts0, kpts1], colors=[kpc0, kpc1], ps=10)

Результат:

2024-04-22_17-56-11