Выравнивание мультиспектральных изображений не удается с помощью ECC

Я пытаюсь выровнять изображение RGB с ИК-изображением (одноканальным). Цель состоит в том, чтобы создать 4-канальное изображение R, G, B, IR. Для этого я использую cv2.findTransformECC, как описано в этот самый аккуратное руководство. На данный момент код не изменился, за исключением строки 13, где для параметра «Движение» задано значение «Евклидово», потому что в будущем я хочу обрабатывать повороты. Я использую Python.

Чтобы проверить работу программного обеспечения, я использовал изображения из руководства. Это работало хорошо, поэтому я хотел сопоставить спутниковые изображения из нескольких спектров, как описано выше. К сожалению, здесь я столкнулся с проблемами.

Иногда алгоритм сходился (по прошествии веков), а иногда он сразу же давал сбой, потому что не мог сходиться, а иногда находил явно неверное решение. В приложении вы найдете два изображения, которые с точки зрения человека легко сопоставить, но алгоритм не работает. Изображения никоим образом не повернуты, они просто не являются одним и тем же изображением (проверьте границы), поэтому ожидается поступательное движение. Изображения озера Нойзидлерзее в Австрии, источник Sentinelhub.

Редактировать: иногда я имею в виду использование разных изображений из Sentinel. Одна пара изображений имеет неизменно одинаковый результат.

Neusieldersee в NIR, данные Sentinel Neusieldersee в RGB, данные Sentinel

Я знаю, что ECC не основан на функциях, что может создать здесь проблему.

Я также читал, что это несколько зависит от исходной матрицы деформации.

Мои вопросы:

  1. Я неправильно использую cv2.findTransformECC?
  2. Есть лучший способ сделать это?
  3. Должен ли я пытаться Монте-Карло исходные матрицы, пока они не сойдутся? (Это кажется неправильным)
  4. Вы предлагаете использовать алгоритм, основанный на функциях?
  5. Если да, есть ли он в наличии или мне придется реализовать это самому?

Спасибо за помощь!


person Clex    schedule 05.07.2021    source источник
comment
Вы можете попробовать выравнивание изображений на основе признаков.   -  person Rotem    schedule 05.07.2021
comment
Спасибо @Rotem за ваш комментарий. Я делал это с самого утра, и это с треском провалилось... То есть с треском! Для меня совершенно ошеломляюще, насколько это плохо. Я открою еще один вопрос о том, как и почему SIFT не может обнаружить и сопоставить хорошо видимые признаки.   -  person Clex    schedule 05.07.2021


Ответы (1)


Вы предлагаете использовать алгоритм, основанный на функциях?

Конечно. Существует множество алгоритмов обнаружения признаков. Обычно я выбираю SIFT, потому что он обеспечивает хорошие результаты сопоставления, а время выполнения достаточно быстрое.

import cv2 as cv
import numpy as np

# read the images
ir = cv.imread('ir.jpg', cv.IMREAD_GRAYSCALE)
rgb = cv.imread('rgb.jpg', cv.IMREAD_COLOR)

descriptor = cv.SIFT.create()
matcher = cv.FlannBasedMatcher()

# get features from images
kps_ir, desc_ir = descriptor.detectAndCompute(ir, mask=None)
gray = cv.cvtColor(rgb, cv.COLOR_BGR2GRAY)
kps_color, desc_color = descriptor.detectAndCompute(gray, mask=None)

# find the corresponding point pairs
if (desc_ir is not None and desc_color is not None and len(desc_ir) >=2 and len(desc_color) >= 2):
    rawMatch = matcher.knnMatch(desc_color, desc_ir, k=2)
matches = []
# ensure the distance is within a certain ratio of each other (i.e. Lowe's ratio test)
ratio = 0.75
for m in rawMatch:
    if len(m) == 2 and m[0].distance < m[1].distance * ratio:
        matches.append((m[0].trainIdx, m[0].queryIdx))

# convert keypoints to points
pts_ir, pts_color = [], []
for id_ir, id_color in matches:
    pts_ir.append(kps_ir[id_ir].pt)
    pts_color.append(kps_color[id_color].pt)
pts_ir = np.array(pts_ir, dtype=np.float32)
pts_color = np.array(pts_color, dtype=np.float32)

# compute homography
if len(matches) > 4:
    H, status = cv.findHomography(pts_ir, pts_color, cv.RANSAC)

warped = cv.warpPerspective(ir, H, (rgb.shape[1], rgb.shape[0]))
warped = cv.cvtColor(warped, cv.COLOR_GRAY2BGR)

# visualize the result
winname = 'result'
cv.namedWindow(winname, cv.WINDOW_KEEPRATIO)
alpha = 5
# res = cv.addWeighted(rgb, 0.5, warped, 0.5, 0)
res = None
def onChange(alpha):
    global rgb, warped, res, winname
    res = cv.addWeighted(rgb, alpha/10, warped, 1 - alpha/10, 0)
    cv.imshow(winname, res)
onChange(alpha)
cv.createTrackbar('alpha', winname, alpha, 10, onChange)
cv.imshow(winname, res)
cv.waitKey()
cv.destroyWindow(winname)

Результат (альфа=8)

результат с альфа=8

Редактировать. Кажется, что SIFT — не лучший вариант, так как он не подходит для некоторых других примеров. Примеры изображений находятся в другом вопросе.

В этом случае я предлагаю использовать SURF. Это запатентованный алгоритм, поэтому он не поставляется с последними установками OpenCV PIP. Вы можете установить предыдущие версии OpenCV или собрать его из исходного кода.

descriptor = cv.xfeatures2d.SURF_create()

Результат (альфа=8)

Результат гомографии SURF

Edit2: Теперь ясно, что ключом к решению этой задачи является выбор правильного дескриптора функции. В заключение я предлагаю выбрать подходящую модель движения. В этом случае аффинное преобразование подходит лучше, чем гомография.

H, _ = cv.estimateAffine2D(pts_ir, pts_color)
H = np.vstack((H, [0, 0, 1]))

Результат аффинного преобразования:

SURF аффинный результат

person Burak    schedule 05.07.2021
comment
Привет, Бурак, спасибо за ваш ответ, пока вы отвечали, я уже написал свое собственное сопоставление с использованием SIFT (я использовал пример tbf), и хотя он, кажется, работает для этой пары изображений (по чистой случайности), он не работает для других и я немного ошеломлен тем, как SIFT может здесь потерпеть неудачу. stackoverflow.com/questions/68256426 / Проверьте результаты в новом потоке. В вашем коде та же проблема, что и в том, что я описал в другом потоке. Он также не может соответствовать другим изображениям. - person Clex; 05.07.2021
comment
@Clex Я посмотрел новый пост, но там нет изображений, чтобы попробовать код. Можете ли вы отредактировать оба сообщения с большим количеством примеров? - person Burak; 05.07.2021
comment
спасибо за вклад, я добавил два изображения, а также руководство о том, как вы можете получить свое собственное. - person Clex; 05.07.2021
comment
@Clex Смотрите редактирование. - person Burak; 06.07.2021