Как неискажать точки в координатах кадра и получить соответствующие неискаженные координаты изображения? - PullRequest
6 голосов
/ 14 декабря 2011

Я использую OpenCV для удаления набора точек после калибровки камеры.Код следует.

const int npoints = 2; // number of point specified 

// Points initialization. 
// Only 2 ponts in this example, in real code they are read from file.
float input_points[npoints][2] = {{0,0}, {2560, 1920}}; 

CvMat * src = cvCreateMat(1, npoints, CV_32FC2);
CvMat * dst = cvCreateMat(1, npoints, CV_32FC2);

// fill src matrix
float * src_ptr = (float*)src->data.ptr;
for (int pi = 0; pi < npoints; ++pi) {
    for (int ci = 0; ci < 2; ++ci) {
        *(src_ptr + pi * 2 + ci) = input_points[pi][ci];
    }
}

cvUndistortPoints(src, dst, &camera1, &distCoeffs1);

После кода выше dst содержит следующие числа:

-8.82689655e-001 -7.05507338e-001 4.16228324e-001 3.04863811e-001

, которые слишком малы по сравнению с числами в src.

В то же время, если я не искажаю изображение с помощью вызова:

cvUndistort2( srcImage, dstImage, &camera1, &dist_coeffs1 );

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

Как получить такое же искажение для определенных точек, как и для изображений?Спасибо.

Ответы [ 3 ]

11 голосов
/ 15 декабря 2011

Точки должны быть «ненормализованы» с использованием матрицы камеры.

Более конкретно, после вызова cvUndistortPoints также должно быть добавлено следующее преобразование:

double fx = CV_MAT_ELEM(camera1, double, 0, 0);
double fy = CV_MAT_ELEM(camera1, double, 1, 1);
double cx = CV_MAT_ELEM(camera1, double, 0, 2);
double cy = CV_MAT_ELEM(camera1, double, 1, 2);

float * dst_ptr = (float*)dst->data.ptr;
for (int pi = 0; pi < npoints; ++pi) {
    float& px = *(dst_ptr + pi * 2);
    float& py = *(dst_ptr + pi * 2 + 1);
    // perform transformation. 
    // In fact this is equivalent to multiplication to camera matrix
    px = px * fx + cx;
    py = py * fy + cy;
}

Более подробная информация о матрице камерыв OpenCV «Калибровка камеры и 3D-реконструкция»

ОБНОВЛЕНИЕ:

Должен также работать следующий вызов функции C ++:

std::vector<cv::Point2f> inputDistortedPoints = ...
std::vector<cv::Point2f> outputUndistortedPoints;
cv::Mat cameraMatrix = ...
cv::Mat distCoeffs = ...

cv::undistortPoints(inputDistortedPoints, outputUndistortedPoints, cameraMatrix, distCoeffs, cv::noArray(), cameraMatrix);
1 голос
/ 14 декабря 2011

Это может быть размер вашей матрицы:)

OpenCV ожидает вектор точек - столбец или матрицу строк с двумя каналами. Но поскольку ваша входная матрица составляет всего 2 точки, а количество каналов также равно 1, она не может определить, что является входом, строкой или столбцом.

Итак, заполните более длинный входной мат фиктивными значениями и оставьте только первое:

const int npoints = 4; // number of point specified 

// Points initialization. 
// Only 2 ponts in this example, in real code they are read from file.
float input_points[npoints][4] = {{0,0}, {2560, 1920}}; // the rest will be set to 0

CvMat * src = cvCreateMat(1, npoints, CV_32FC2);
CvMat * dst = cvCreateMat(1, npoints, CV_32FC2);

// fill src matrix
float * src_ptr = (float*)src->data.ptr;
for (int pi = 0; pi < npoints; ++pi) {
    for (int ci = 0; ci < 2; ++ci) {
        *(src_ptr + pi * 2 + ci) = input_points[pi][ci];
    }
}

cvUndistortPoints(src, dst, &camera1, &distCoeffs1);

EDIT

Хотя OpenCV указывает undistortPoints, принимают только 2-канальный ввод, фактически он принимает

  • 1-колоночный, 2-канальный, многорядный мат или (и этот случай не задокументирован)
  • 2 столбца, многорядный, 1-канальный мат или
  • мультиколонка, 1 ряд, 2-канальный коврик

(как видно из undistort.cpp, строка 390)

Но внутренняя ошибка (или отсутствие доступной информации) приводит к неправильному смешиванию второго с третьим, когда количество столбцов равно 2. Итак, ваши данные считаются двухстрочными, двухрядными, 1-канальный.

0 голосов
/ 07 января 2019

Я также достигаю этой проблемы, и мне нужно время, чтобы исследовать, наконец, понять.

<img src="https://i.stack.imgur.com/nmR5P.jpg"></img>

Формула Вы видите формулу выше, в открытой системе операция искажения выполняется перед матрицей камеры, поэтому порядок обработки:
image_distorted-> camera_matrix -> un-distort function-> camera_matrix-> вернуться к image_undistorted.

Так что вам нужно немного исправить и camera1 снова.
Mat eye3 = Mat :: eye (3, 3, CV_64F);
cvUndistortPoints (src, dst, & camera1, & distCoeffs1, & eye3, & camera1 );

В противном случае, если два последних параметра пусты, проект будет преобразован в нормализованную координату изображения.

См. Коды: opencv-3.4.0-src \ modules \ imgproc \ src \ undistort.cpp: 297 cvUndistortPointsInternal ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...