2017-11-16 22 views
2

this question과 비슷한 것을하고 싶습니다. calibrateCamera() 대신 stereoCalibrate()을 사용하고 싶습니다. 즉, 스테레오 카메라 보정을위한 재 투영 오류를 계산합니다.OpenCV + Python : 스테레오 재 투영 오류 계산

내 감소 된 예는 다음과 같습니다

import cv2 
import numpy as np 

def calibrate_stereo(w, h, objpoints, imgpoints_l, imgpoints_r): 
    stereocalib_criteria = (cv2.TERM_CRITERIA_COUNT + cv2.TERM_CRITERIA_EPS , 1000, 1e-6) 
    retval, A1, D1, A2, D2, R, T, E, F = cv2.stereoCalibrate(objpoints,imgpoints_l, imgpoints_r,None,None,None,None, (w,h), flags=0, criteria=stereocalib_criteria) 

    return (retval, (A1,D1,A2,D2, R, T, E, F)) 

def calc_rms_stereo(objectpoints, imgpoints_l, imgpoints_r, A1, D1, A2, D2, R, T): 
    tot_error = 0 
    total_points = 0 

    for i, objpoints in enumerate(objectpoints): 
     # calculate world <-> cam1 transformation 
     _, rvec_l, tvec_l,_ = cv2.solvePnPRansac(objpoints, imgpoints_l[i], A1, D1) 

     # compute reprojection error for cam1 
     rp_l, _ = cv2.projectPoints(objpoints, rvec_l, tvec_l, A1, D1) 
     tot_error += np.sum(np.square(np.float64(imgpoints_l[i] - rp_l))) 
     total_points += len(objpoints) 

     # calculate world <-> cam2 transformation 
     rvec_r, tvec_r = cv2.composeRT(rvec_l,tvec_l,cv2.Rodrigues(R)[0],T)[:2] 

     # compute reprojection error for cam2 
     rp_r,_ = cv2.projectPoints(objpoints, rvec_r, tvec_r, A2, D2) 
     tot_error += np.square(imgpoints_r[i] - rp_r).sum() 
     total_points += len(objpoints) 

    mean_error = np.sqrt(tot_error/total_points) 

    return mean_error 


if __name__ == "__main__":  
    # omitted: reading values for w,h, objectPoints, imgpoints_l, imgpoints_r from file (format as expected by the OpenCV functions) 
    # [...] 

    rms, (A1,D1,A2,D2,R,T,_,_) = calibrate_stereo(w, h, objectpoints, imgpoints_l, imgpoints_r) 

    print("RMS (stereo calib): {}".format(rms)) 

    rms_2 = calc_rms_stereo(objectpoints, imgpoints_l, imgpoints_r, A1, D1, A2, D2, R, T)  
    print("RMS (custom calculation):", rms_2) 

샘플 출력 :

RMS (stereo calib): 0.14342257926694932 
RMS (custom calculation): 0.356273345751 

는 지금까지 내가 말할 수있는, stereoCalibrate()의 소스 코드의 계산이 광산과 매우 유사합니다. 내가 뭘 놓치고 있니? 우분투

+0

스테레오의 소스 코드에 대해 이해 한 점은 오류 (norm (ab))가 오류에 추가 된 지점 사이의 거리를 계산 한 다음이를 나누어서 제곱근을 얻는 것입니다. 포인트 구성 요소의 차이와 제곱근을 할거야 ... 어쩌면 내가 틀렸어 – api55

+0

@ api55 그건 내가 생각한거야. 나는 당신이 [이 줄] (https://github.com/opecv/opencv/blame/master/modules/calib3d/src/calibration.cpp#L2152)을 의미한다고 생각하지만 실제로 [square norm] (https : //stackoverflow.com/questions/32887671/does-opencv-offer-a-squared-norm-function-for-cvpoint) – TheBender

+0

정확히 하나. 또한 의미가 있습니다. RMSE는 제곱 오류 평균의 근원이지만 오류로 정의한 내용에 따라 다릅니다. 제가 아는 한, 재 투영 오차는 2D에서 투영 된 점과 2D 점에서 첫 번째 점에서 3D 점을 생성하는 데 사용되는 거리입니다. – api55

답변

0

OpenCV의 3.3.0는 내가 OpenCV의 구현에 따라 사용자 정의 스테레오 보정 알고리즘을 구현 한 후 그것을 해결.

cv2.stereoCalibrate()에서 계산 된 재 투영 오차와 내 사용자 정의 계산의 차이는 외재 매개 변수 rvec_ltvec_l에 대한 다른 값에서 유래합니다. 이 벡터는 왼쪽 카메라와 각 이미지의 교정 패턴 사이의 회전과 이동을 나타냅니다. cv2.solvePnpRansac()은 왼쪽 이미지의 재 투영 오류만을 기반으로 최적화 된 값을 산출하며 cv2.stereoCalibrate()에서는 각 스테레오 쌍의 두 이미지에서 재 투영 오류를 기준으로 RT과 함께 이들 값이 최적화됩니다. 하나는 정확히 cv2.stereoCalibrate()에 의해 반환되는 RMS 값을 복제하고자하는 경우, 하나는뿐만 아니라 최적화 된 외부 매개 변수를 반환하는 cv::stereoCalibrate()의 C/C++ 소스 코드를 수정해야

(cv::calibrateCamera()는 이미 단안 교정 수행)을.