Фон:
В настоящее время я работаю над проектом стереовидения с использованием 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.