Как работает метод калибровки Тоскани и Фожераса?Python

Программы на Python
Ответить
Anonymous
 Как работает метод калибровки Тоскани и Фожераса?

Сообщение Anonymous »

Сначала я попробовал базовый подход, чтобы получить параметры камеры.
В матрице A у вас есть два уравнения, которые может дать 3D-точка (умноженные на число точек):
Поскольку у нас есть uZ -uoZ -px =0 и vZ -v0Z - py=0
Тогда у нас есть A*X=0 где X представляет собой неизвестно, а A представляет наблюдаемые.
Чтобы решить X, в идеальном сценарии мы должны выполнить разложение по сингулярным значениям (SVD) A. X связан с наименьшим значением в D.
Однако есть проблема: X = 0 — допустимое решение! Поэтому я думаю, что СВД дает именно такое решение, а не то, которое мы ищем. Я не уверен, есть ли проблема в моем коде или это просто «нормально».
objpoints находится в опорном кадре шахматной доски, а imgpoints — в опорном кадре камеры. (они рассчитаны ниже)

Код: Выделить всё

    A = []
for i in range(len(objpoints)):
X, Y, Z = objpoints[i]
u, v = imgpoints[i][0]

row1 = [u*X, u*Y, u*Z, -X, -Y, -Z, 0, 0, 0, -1, 0, u]
row2 = [v*X, v*Y, v*Z, 0, 0, 0, -X, -Y, -Z, 0, -1, v]

A.append(row1)
A.append(row2)

A = np.array(A)

# Solve the homogeneous system using SVD
_, _, V = np.linalg.svd(A)
X = V[:, -1]
print("Estimated Camera Parameters:", X)

print("uo:",X[0]*X[3]+X[1]*X[4]+X[2]*X[6])
В методе Тоскани и Фожераса все немного по-другому.
На этот раз мы не решаем AX, потому что 0 может быть решением.
Вместо этого мы пытаемся минимизировать следующую функцию стоимости C=||A

Код: Выделить всё

X1 + B*X2||

Код: Выделить всё

2 + (1-X1)
[/b] ;
При таком подходе проблема была декомпозирована. и [/b]

Код: Выделить всё

=[X1,X2,X3]
(три первых параметра, которые мы получили ранее)

Код: Выделить всё

B=[[-X, -Y, -Z, 0, 0, 0, -1, 0, u],[ 0, 0, 0, -X, -Y, -Z, 0, -1, v]]
и [/b]

Код: Выделить всё

=[X4,..,X12]
(остальное)
Дифференцируя C, мы можем получить **решение ** проблемы.
Производная
и затем :
Решение
Как видите, нам нужно вычислить обратную величину B.T @ B, чтобы получить некоторые параметры ( не все!).
Однако я есть БОЛЬШАЯ проблема: BT @ B должен быть обратимым. Когда я смотрю на этот метод, мне кажется, что нет причин, по которым этого не должно быть! Между строками и столбцами нет явной зависимости!
Однако в написанном мною коде (который вы можете найти ниже) я получаю** ошибку о том, что матрица сингулярна** . Я всмотрелся, и действительно, матрица 9х9 не полного ранга (8-го ранга, если быть точным). Это делает невозможным вычисление X1 и X2. Я не уверен, допустил ли я ошибку в своих расчетах, обработке матрицы или этот метод просто предназначен для использования в определенном контексте. Сейчас я пытаюсь заставить его работать на изображении шахматной доски из руководства по калибровке OpenCV.
Вот код, о котором идет речь. Должно отображаться:

Код: Выделить всё

Cx= X[0]*X[3]+X[1]*X[4]+X[2]*X[6]
который представляет центр изображения вместе с Cy. Однако в итоге я получил значение около 10^(-3) , что далеко от ожидаемых 400, заданных OpenCV. р>

Код: Выделить всё

import numpy as np
import cv2
import glob

CHECKERBOARD = (6, 9)
square_size = 3

def calibration(CHECKERBOARD,square_size):
objp = np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2) * square_size
objpoints = []
imgpoints = []

images = glob.glob('Folder/*.jpg')
#Only for one image.  I have to remove the loop
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
if ret:
objpoints=objp
imgpoints=corners
cv2.drawChessboardCorners(img, CHECKERBOARD, corners, ret)
cv2.imshow('Image', img)
cv2.waitKey()
else:
print(ret)

cv2.destroyAllWindows()

A = np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1] * 2, 3), np.float32)
B = np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1] * 2, 9), np.float32)
#Algo 1: using Toscani Faugeras approach
for i in range (CHECKERBOARD[0] * CHECKERBOARD[1]):
X,Y,Z= objpoints[i]
u,v=imgpoints[i][0]

A[2*i][0]=u*X
A[2*i][1]=u*Y
A[2*i][2]=u*Z

A[2*i+1][0]=v*X
A[2*i+1][1]=v*Y
A[2*i+1][2]=v*Z

B[2*i][0]=-X
B[2*i][1]=-Y
B[2*i][2]=-Z
#B[2*i][3]=0
#B[2*i][4]=0
#B[2*i][5]=0
B[2*i][6]=-1
B[2*i][7]=0
B[2*i][8]=u

#B[2*i+1][0]=0
#B[2*i+1][1]=0
#B[2*i+1][2]=0
B[2*i+1][3]=-X
B[2*i+1][4]=-Y
B[2*i+1][5]=-Z
B[2*i+1][6]=0
B[2*i+1][7]=-1
B[2*i+1][8]=v

print(B) #Is there a problem?
E = A.T @ A - A.T @ B @ np.linalg.inv(B.T @ B) @ B.T @ A
eigenvalues, eigenvectors = np.linalg.eig(E)
X1 = eigenvectors[:, np.argmin(eigenvalues)]
X2 = -np.linalg.pinv(B.T @ B) @ B.T @ A @ X1
print("X1",X1,"X2",X2)
#print([i for i in range (9) if ((B.T @ B)[i,i]==0)] ) #2 erreurs
#print(np.linalg.matrix_rank((B.T @ B)))

print(X[0]*X[3]+X[1]*X[4]+X[2]*X[6])

calibration(CHECKERBOARD,square_size)
Я не смог найти в Интернете ничего по этому поводу. Кажется, изучить это довольно сложно.
Если кто-то увидит проблему в коде или подходе, спасибо! Я знаю, что это не лучший метод, но я хотел попробовать его и сравнить результаты с функциями OpenCV.

Подробнее здесь: https://stackoverflow.com/questions/792 ... geras-work
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»