Извлечение поступательной информации без вращения из матрицы преобразования?

Я использую детектор функций SIFT, и мне нужен угол И перемещение центра двух преобразованных изображений с жесткими 2D-изображениями. Поэтому я хочу извлечь информацию непосредственно из матрицы преобразования.

Во вложении минимальный рабочий пример. Идея состоит в том, чтобы построить матрицу вращения с углом, который я получаю при регистрации изображения, а затем извлечь обратно путем умножения матрицы матрицу перевода. Я думаю, что это должно работать, но не хватает какой-то мелочи. Цель минимального рабочего примера — вычислить начальные заданные параметры (tx,ty,angle) на основе регистрации изображения.

import numpy as np
import cv2 as cv, cv2
import matplotlib.pyplot as plt
import math

img=cv2.imread(r"\lena_std.tif",cv2.IMREAD_GRAYSCALE)

tx=0 #parameters to play which should be totally compensated by the code
ty=0
angle=60

rows,cols= img.shape

rot_mat = cv2.getRotationMatrix2D((cols/2,rows/2),angle,1)
rot_mat=np.vstack([rot_mat, np.array([0,0,1])])
trans_mat = np.array([
    [1, 0, tx],
    [0, 1, ty],
    [0, 0, 1]
], dtype=np.float32)
M=trans_mat @ rot_mat

reference_image = img
test_image = cv2.warpAffine(img,M[:2,:3],(cols,rows))

def similarity_sift_flann_affine2D (reference_image, test_image):

    img1=test_image.astype(np.uint8)
    img2=reference_image.astype(np.uint8)

    # Initiate SIFT detector
    sift = cv.SIFT_create()
    # find the keypoints and descriptors with SIFT
    kp1, des1 = sift.detectAndCompute(img1,None)
    kp2, des2 = sift.detectAndCompute(img2,None)
    FLANN_INDEX_KDTREE = 1
    index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    search_params = dict(checks = 50)
    flann = cv.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(des1,des2,k=2)
    # store all the good matches as per Lowe's ratio test.
    good = []
    for m,n in matches:
        if m.distance < 0.7*n.distance:     #Lowes ratio test
            good.append(m)
        
    MIN_MATCH_COUNT=10
        
    if len(good)>=MIN_MATCH_COUNT:
        src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
        dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
        M, mask = cv2.estimateAffinePartial2D(src_pts, dst_pts)
        #M,mask = cv.estimateAffine2D(src_pts, dst_pts)
    
    else:
        print( "Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT) )
        matchesMask = None
        
    return M

M1=similarity_sift_flann_affine2D (reference_image, test_image)

sizeImg1=img.shape
u, _, vh = np.linalg.svd(M[0:2, 0:2])   
R = u @ vh
angle2 = math.atan2(R[1,0], R[0,0])
angle2 =np.rad2deg(angle2)

cor_rot_mat = cv2.getRotationMatrix2D((cols/2,rows/2),-angle2,1)
cor_rot_mat=np.vstack([cor_rot_mat, np.array([0,0,1])])

M1=np.vstack([M1, np.array([0,0,1])])
#cor_trans_mat= np.linalg.inv(cor_rot_mat) @ M1
cor_trans_mat= M1 @ np.linalg.inv(cor_rot_mat)

print("angle diff", str(np.abs(angle2)-np.abs(angle)))
print("tx diff", str(np.abs(tx)-np.abs(cor_trans_mat[0][2])))
print("ty diff", str(np.abs(ty)-np.abs(cor_trans_mat[1][2])))

Может ли кто-нибудь помочь? Большое спасибо!

Что вы подразумеваете под «с не зависящими от угла переводами». Определите, насколько вам нужен перевод. Коэффициенты cv2.estimateAffinePartial2D() должны дать вам угол и переводы. См. матрицу по адресу docs.opencv.org/4.1.1/d9/d0c/…

fmw42 12.04.2024 20:31

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

TMul 12.04.2024 21:33

Разве вы не можете использовать часть матрицы вращения, чтобы повернуть центральную точку, а затем вычесть ее из исходного центра? Это то что ты хочешь?

fmw42 12.04.2024 22:59

Привет @fmw42, да, это именно то, что я хочу и что я пробовал. Но в зависимости от того, в какой точке (центр, угол,...) я поворачиваю изображение, всегда есть точка (центр вращения), на которую вращение не влияет, и к этой точке я должен иметь возможность применить информацию о переводе матрица напрямую. Но поскольку параметры перевода изменяются в зависимости от угла, это, похоже, не работает. Чего я не понимаю? Насколько я понимаю, матрица преобразования сопоставляет каждую точку изображения 2 с изображением 1.

TMul 13.04.2024 11:10

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

Community 14.04.2024 10:04

Я постарался сделать вопрос более ясным.

TMul 14.04.2024 11:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
6
99
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел решение, теория моего кода оказалась верной. Ошибка заключалась в знаке угла 2, и я закомментировал неправильное умножение обратной матрицы.

Этот код работает:

import numpy as np
import cv2 as cv, cv2
import matplotlib.pyplot as plt
import math

img=cv2.imread(r"\lena_std.tif",cv2.IMREAD_GRAYSCALE)

tx=36 #parameters to play which should be totally compensated by the code
ty=120
angle=30

rows,cols= img.shape

rot_mat = cv2.getRotationMatrix2D((cols/2,rows/2),angle,1)
rot_mat=np.vstack([rot_mat, np.array([0,0,1])])
trans_mat = np.array([
    [1, 0, tx],
    [0, 1, ty],
    [0, 0, 1]
], dtype=np.float32)
M=trans_mat @ rot_mat

reference_image = img
test_image = cv2.warpAffine(img,M[:2,:3],(cols,rows))

def similarity_sift_flann_affine2D (reference_image, test_image):

    img1=test_image.astype(np.uint8)
    img2=reference_image.astype(np.uint8)

# Initiate SIFT detector
    sift = cv.SIFT_create()
# find the keypoints and descriptors with SIFT
    kp1, des1 = sift.detectAndCompute(img1,None)
    kp2, des2 = sift.detectAndCompute(img2,None)
    FLANN_INDEX_KDTREE = 1
    index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    search_params = dict(checks = 50)
    flann = cv.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(des1,des2,k=2)
# store all the good matches as per Lowe's ratio test.
    good = []
    for m,n in matches:
        if m.distance < 0.7*n.distance:     #Lowes ratio test
        good.append(m)
    
    MIN_MATCH_COUNT=10
    
    if len(good)>=MIN_MATCH_COUNT:
        src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
        dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
        M, mask = cv2.estimateAffinePartial2D(src_pts, dst_pts)
        #M,mask = cv.estimateAffine2D(src_pts, dst_pts)

    else:
        print( "Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT) )
        matchesMask = None
    
    return M

M1=similarity_sift_flann_affine2D (reference_image, test_image)

sizeImg1=img.shape
u, _, vh = np.linalg.svd(M[0:2, 0:2])   
R = u @ vh
angle2 = math.atan2(R[1,0], R[0,0])
angle2 =np.rad2deg(angle2)

cor_rot_mat = cv2.getRotationMatrix2D((cols/2,rows/2),angle2,1)
cor_rot_mat=np.vstack([cor_rot_mat, np.array([0,0,1])])

M1=np.vstack([M1, np.array([0,0,1])])
cor_trans_mat= np.linalg.inv(cor_rot_mat) @ M1

print("angle diff", str(np.abs(angle2)-np.abs(angle)))
print("tx diff", str(np.abs(tx)-np.abs(cor_trans_mat[0][2])))
print("ty diff", str(np.abs(ty)-np.abs(cor_trans_mat[1][2])))

Другие вопросы по теме