Próbuję przeprowadzić kalibrację i znaleźć lokalizację i obrót pojedynczej wirtualnej kamery w Blenderze 3d za pomocą homografii. Używam Blendera, aby móc dwukrotnie sprawdzić wyniki, zanim przejdę do prawdziwego świata, w którym jest to trudniejsze. Wykonałem dziesięć zdjęć szachownicy w różnych miejscach i obrotach w widoku mojej nieruchomej kamery. W pythonie opencv użyłem cv2.calibrateCamera, aby znaleźć wewnętrzną matrycę z wykrytych rogów szachownicy na dziesięciu obrazach, a następnie wykorzystałem to w cv2.solvePnP, aby znaleźć zewnętrzne parametry (translacja i obrót). Mimo że szacowane parametry były zbliżone do rzeczywistych, dzieje się coś podejrzanego. Moje wstępne oszacowanie tłumaczenia wyniosło (-0,11205481, -0,0490256,8.13892491). Rzeczywista lokalizacja była (0,0,8.07105). Całkiem blisko, prawda? Ale kiedy przeniosłem się i lekko obróciłem kamerę, a obrazy zostały ponownie zarchiwizowane, szacowane tłumaczenie stało się dalej. Szacowane: (-0,155933154,0.13367286,9.34058867). Rzeczywiste: (-1.7918, -1,51073,9.76597). Wartość Z jest blisko, ale X i Y nie są. Jestem całkowicie zdezorientowany. Jeśli ktokolwiek może mi pomóc rozwiązać ten problem, byłbym bardzo wdzięczny. Oto kod (jest oparty off python2 kalibracji przykład dostarczany z OpenCV):Python Opencv SolvePnP daje zły wektor translacji
#imports left out
USAGE = '''
USAGE: calib.py [--save <filename>] [--debug <output path>] [--square_size] [<image mask>]
'''
args, img_mask = getopt.getopt(sys.argv[1:], '', ['save=', 'debug=', 'square_size='])
args = dict(args)
try: img_mask = img_mask[0]
except: img_mask = '../cpp/0*.png'
img_names = glob(img_mask)
debug_dir = args.get('--debug')
square_size = float(args.get('--square_size', 1.0))
pattern_size = (5, 8)
pattern_points = np.zeros((np.prod(pattern_size), 3), np.float32)
pattern_points[:,:2] = np.indices(pattern_size).T.reshape(-1, 2)
pattern_points *= square_size
obj_points = []
img_points = []
h, w = 0, 0
count = 0
for fn in img_names:
print 'processing %s...' % fn,
img = cv2.imread(fn, 0)
h, w = img.shape[:2]
found, corners = cv2.findChessboardCorners(img, pattern_size)
if found:
if count == 0:
#corners first is a list of the image points for just the first image.
#This is the image I know the object points for and use in solvePnP
corners_first = []
for val in corners:
corners_first.append(val[0])
np_corners_first = np.asarray(corners_first,np.float64)
count+=1
term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
cv2.cornerSubPix(img, corners, (5, 5), (-1, -1), term)
if debug_dir:
vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.drawChessboardCorners(vis, pattern_size, corners, found)
path, name, ext = splitfn(fn)
cv2.imwrite('%s/%s_chess.bmp' % (debug_dir, name), vis)
if not found:
print 'chessboard not found'
continue
img_points.append(corners.reshape(-1, 2))
obj_points.append(pattern_points)
print 'ok'
rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h))
print "RMS:", rms
print "camera matrix:\n", camera_matrix
print "distortion coefficients: ", dist_coefs.ravel()
cv2.destroyAllWindows()
np_xyz = np.array(xyz,np.float64).T #xyz list is from file. Not shown here for brevity
camera_matrix2 = np.asarray(camera_matrix,np.float64)
np_dist_coefs = np.asarray(dist_coefs[:,:],np.float64)
found,rvecs_new,tvecs_new = cv2.solvePnP(np_xyz, np_corners_first,camera_matrix2,np_dist_coefs)
np_rodrigues = np.asarray(rvecs_new[:,:],np.float64)
print np_rodrigues.shape
rot_matrix = cv2.Rodrigues(np_rodrigues)[0]
def rot_matrix_to_euler(R):
y_rot = asin(R[2][0])
x_rot = acos(R[2][2]/cos(y_rot))
z_rot = acos(R[0][0]/cos(y_rot))
y_rot_angle = y_rot *(180/pi)
x_rot_angle = x_rot *(180/pi)
z_rot_angle = z_rot *(180/pi)
return x_rot_angle,y_rot_angle,z_rot_angle
print "Euler_rotation = ",rot_matrix_to_euler(rot_matrix)
print "Translation_Matrix = ", tvecs_new
Dziękuję bardzo
Mam ten sam problem, używam innej metody chociaż. Mam nadzieję, że ktoś zna odpowiedź. http://stackoverflow.com/questions/14444433/calculate-camera-world-position-with-opencv-python –
nie potrzebujesz własnej rot_matrix_to_euler, Rodrigues robi to za Ciebie – Hammer
Cóż, b_m, wygląda na to, że jesteśmy w tej samej łodzi haha. Mam nadzieję, że ktoś będzie w stanie nam pomóc. Jak mogę uzyskać kąty Eulera bezpośrednio od Rodriguesa? Wektor obrotu 3x1 nie jest taki sam, jak kąty Eulera dla mnie. Czy moje dane wejściowe do solvePnP są poprawne? Czy w ten sposób używasz danych wyjściowych z calibratecamera? – amartin7211