Я заметил, что opencv StereoCalibrate () изменяет фокусные расстояния в матрицах камеры, даже если я установил соответствующий флаг (например, CV_CALIB_FIX_FOCAL_LENGTH). Я использую две одинаковые камеры с одинаковым фокусным расстоянием, установленным механически на объективе, и, кроме того, я знаю размер сенсора, чтобы я мог вычислить собственную матрицу камеры вручную, что на самом деле я делаю.
Здесь у вас есть выход из программы стереокалибровки — матрицы камер до и после стереокалибровки ().
std::cout << "Before calibration: " << std::endl;
std::cout << "C1: " << _cameraMatrixA << std::endl;
std::cout << "C2: " << _cameraMatrixB << std::endl;
double error = cv::stereoCalibrate(objectPoints, imagePointsA, imagePointsB, _cameraMatrixA, _distCoeffsA, _cameraMatrixB, _distCoeffsB, _imageSize,
R, T, E, F,
cv::TermCriteria((cv::TermCriteria::COUNT + cv::TermCriteria::EPS), 30, 9.999999999999e-7), CV_CALIB_FIX_FOCAL_LENGTH | CV_CALIB_FIX_PRINCIPAL_POINT);
std::cout << "After calibration: " << std::endl;
std::cout << "C1: " << _cameraMatrixA << std::endl;
std::cout << "C2: " << _cameraMatrixB << std::endl;
Перед калибровкой:
C1: [6203,076923076923, 0, 1280; 0,
6203.076923076923, 960; 0, 0, 1]С2: [6203,076923076923, 0, 1280; 0, 6203.076923076923, 960; 0, 0,
1]После калибровки:
C1: [6311,77650416514, 0, 1279,5; 0, 6331,34531760757, 959,5; 0,
0, 1]С2: [6152,655897294907, 0, 1279,5; 0, 6206,591406832492, 959,5; 0,
0, 1]
Я думаю, что это странное поведение opencv. Кто-нибудь сталкивался с подобной проблемой? Я знаю, что это легко решить, я могу просто установить фокусное расстояние для матриц камеры после стереокалибровки.
Для того, чтобы делать то, что вы хотите, вы должны позвонить stereoCalibrate
с флагами:
CV_CALIB_USE_INTRINSIC_GUESS | CV_CALIB_FIX_FOCAL_LENGTH | CV_CALIB_FIX_PRINCIPAL_POINT
Если вы не используете CV_CALIB_USE_INTRINSIC_GUESS
флаг, stereoCalibrate
сначала инициализирует матрицы камеры и коэффициенты искажения, а затем исправит их часть при последующей оптимизации. Это указано в документация, хотя довольно неясно и без упоминания этого критического флага:
Помимо информации, связанной со стерео, функция также может выполнять полную калибровку каждой из двух камер. Однако из-за высокой размерности пространства параметров и шума во входных данных функция может отличаться от правильного решения. Если внутренние параметры могут быть оценены с высокой точностью для каждой камеры отдельно (например, с помощью calibrateCamera ()), рекомендуется сделать это […].
С помощью CV_CALIB_USE_INTRINSIC_GUESS
в дополнение к любому из CV_CALIB_FIX_*
flags указывает функции использовать то, что вы передаете в качестве ввода, в противном случае этот ввод просто игнорируется и перезаписывается.
флаг CV_CALIB_FIX_FOCAL_LENGTH заставляет подпрограмму оптимизации просто использовать Fx и Fy, которые были переданы во внутренней матрице.