Подтвердить что ты не робот

Что такое "приемлемое" значение возврата из cv:: calibrateCamera?

Фон:

В настоящее время я работаю над проектом стереовидения с использованием OpenCV. Я пытаюсь создать карту несоответствий из набора двух исправленных изображений, но я не получаю ожидаемого результата. При просмотре исправленных изображений наблюдается заметное вертикальное смещение между изображениями, которое не должно быть после исправления. В настоящее время я ищу, что может быть ошибкой. Мой код основан на методе калибровки стерео и кода соответствия из книги OpenCV, а в этом примере. Я использую С++-интерфейс OpenCV. Моя версия OpenCV 2.1, из репозитория Ubuntu 11.04.

Короткий вариант вопроса:

Какое возвращаемое значение RMS приемлемо для функции:

double cv::calibrateCamera(...)

В настоящее время я откалибрую каждую камеру, используя набор из 20 пар изображений шахматной доски. Камеры двух одинаковых PS3 Eyes (с разрешением 640 * 480 пикселей) установлены рядом друг с другом. cv::calibrateCamera возвращает ошибку RMS между 160 и 300 (у меня был другой результат с разными наборами изображений). Является ли это приемлемым значением для этого разрешения изображения или я должен попытаться улучшить изображение шахматной доски?

Длинная версия (подробности, примеры кода):

Чтобы получить рабочее стереовидение; во-первых, я хочу убедиться, что процедура калибровки камеры работает правильно. Я использую серию изображений шахматной доски для калибровки моей стереофонической установки, например:

// Find chessboard corners
cv::Mat left = ... //Load image
vector<cv::Point2f> points;

bool found = cv::findChessboardCorners(left, patternSize, points, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);
if(found)
  cv::cornerSubPix(left, points, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
imagePointsLeft.push_back(points);

Я делаю это для нескольких пар изображений и помещаю результирующие точки в imagePointsLeft и imagePointsRight. Я проверил отдельную программу на тех же изображениях, где я наглядно подтверждаю, что левое и правое изображения правильно регистрируют все углы в том же порядке, используя cv::drawChessboardCorners. Для каждой пары изображений я также заполняю набор координат объекта так:

vector<cv::Point3f> obj;
for(int i = 0; i < ny; i++)
  for(int j = 0; j < nx; j++)
    obj.push_back(cv::Point3f(i*squareSize,j*squareSize,0.0));
objectPoints.push_back(obj);

Затем я пытаюсь выполнить калибровку камер с этими изображениями:

double rms = cv::calibrateCamera(objectPoints, imagePointsLeft, m_imageSize, m_cameraMatrixLeft, m_distortionMatrixLeft, rvecsLeft, tvecsLeft);

Я использую встроенные функции камеры из этой функции, когда я вызываю cv::stereoCalibrate с помощью флага CV_CALIB_FIX_INTRINSIC (этот способ стерео калибровки предлагается в документации, здесь).

Я перешёл на вызов cv::stereoRectify и cv::initUndistortRectifyMap, последний для обеих камер. Выпрямленные изображения создаются с помощью cv::remap с использованием выхода initUndistortRectifyMap и камеры в режиме реального времени. Оба изображения содержат только действительные пиксели (без черных областей). Моя проблема в том, что пиксели данной строки не совпадают с одной и той же строкой на другом изображении (имеется небольшое смещение по вертикали). Это затрудняет получение хороших результатов от алгоритмов соответствия, таких как StereoBM.

4b9b3361

Ответ 1

Проблема с калибровкой камеры: cv::calibrateCamera() возвращает ошибку рецензирования среднего квадрата (RMS) [1] и должна быть между 0,1 и 1,0 пикселями в хорошей калибровке. Для точки отсчета я получаю примерно 0.25 px RMS-ошибку, используя мою собственную стереокамеру, сделанную из двух аппаратно-синхронизированных камер Playstation Eye, работающих под разрешением 640 x 480.

Вы уверены, что координаты пикселей, возвращаемые cv::findChessboardCorners(), находятся в том же порядке, что и в obj? Если оси были перевернуты, вы получите симптомы, похожие на те, которые вы описываете.

[1]: OpenCV вычисляет ошибку репроцессинга, проецируя трехмерные точки шахматной доски на изображение, используя окончательный набор параметров калибровки и сравнивая положение углов. RMS-ошибка 300 означает, что в среднем каждая из этих прогнозируемых точек составляет 300 пикселей от ее фактического положения.