Перейти к содержимому
Compvision.ru
Smorodov

Программка калибрующая камеру

Recommended Posts

Кстати. В gimp'е есть фильтр "убрать искажение оптики". Там несколько движков, передвигая которые можно убирать дисторсию.

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

Ещё есть убирание дисторсии в проекте с открытыми исходниками IVT. Пример называется UndistortionRectificationDemo. В этом же примере есть "выпрямление" изображения, если оно снималось под наклоном.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ещё есть убирание дисторсии в проекте с открытыми исходниками IVT. Пример называется UndistortionRectificationDemo. В этом же примере есть "выпрямление" изображения, если оно снималось под наклоном.

Можна вопрос???

Не могу понять что-это за ресурс IVT. Это еще ожни библиотеки, че-то наподобе ОпенСв... Или я ошибаюсь...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не ошибаешься.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не ошибаешься.

А какой из этих вариантов тогда выходит лучше!!!! OpenCV или IVT???? или это дело выбора???

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Что тебе на текущий момент больше подходит, то и выбирай. OpenCV хорошая, но неидеальная библиотека. Ну и никто не запрещает использовать и то, и другое одновременно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Что тебе на текущий момент больше подходит, то и выбирай. OpenCV хорошая, но неидеальная библиотека. Ну и никто не запрещает использовать и то, и другое одновременно.

Спасибо за инфу!!!!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Всем, привет! =)

Ну как, в итоге что-нибудь получилось?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я как-то писал:

С эпиполярными линиями все понятно, все работает почти при любых позициях камер.

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

До того как я это узнал, прошло много времени. Потом я попытался всё сделать по-другому, составил громадную систему уравнений, там остаются неизвестные.

Недавно нашел одну хорошую книгу на Английском, пробежался по картинкам, но еще не читал.

На этом пока остановился. Не хватает времени и идей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А книжка не Multiple View Geometry ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Чуть-чуть не в тему, на калибровку я забил пока, калибрую по доске, оттуда же беру матрицы трансформации. Не получается из соответствующих точек на двух изображениях получить 3D координату.

Нашел вот такую презентацию еще, там кусок из Multiple View Geometry как раз то, что надо, все разложено по полочкам:

http://users.cecs.anu.edu.au/~luke/cvcourse_files/online_notes/lectures_3D_5_calibrated_recon.pdf

Написал функцию, вроде все правильно, а в итоге вообще не понимаю, в каких координатах она мне что возвращает и как это привязать к камере. Даже расстроился, столько времени потратил, вроде вот оно, а до конца разобраться не получается. Может там всего-то надо домножить на внутренние параметры камеры где-то?


//CvMat* x1 = cvCreateMat(3,1,CV_32FC1); // Точка на первом изображении в виде матрицы [x y 1] (координаты в пикселях)

//CvMat* x2 = cvCreateMat(3,1,CV_32FC1); // Соответствующая точка на втором изображении

//CvMat* P = cvCreateMat(3,4,CV_32FC1); // Относительное перемещение камеры между кадрами

//CvMat* Х = cvCreateMat(3,1,CV_32FC1); // output - Получаю точку [X Y Z] по идее в координатах первой камеры 


void TwoViewTriangulation(CvMat *x1, CvMat *x2, CvMat *P, CvMat *X) {

  CvMat* P1cam = cvCreateMat(3,4,CV_32FC1);

  CvMat* P2cam = cvCreateMat(3,4,CV_32FC1);

  CvMat* A = cvCreateMat(4,4,CV_32FC1);

  CvMat* Anorm = cvCreateMat(4,4,CV_32FC1);

  CvMat* U = cvCreateMat(4,4,CV_32FC1);

  CvMat* D = cvCreateMat(4,4,CV_32FC1);

  CvMat* Vt = cvCreateMat(4,4,CV_32FC1);


  // P1cam = [ I | 0 ]

  cvmSet(P1cam,0,0, 1); cvmSet(P1cam,0,1, 0); cvmSet(P1cam,0,2, 0); cvmSet(P1cam,0,3, 0);

  cvmSet(P1cam,1,0, 0); cvmSet(P1cam,1,1, 1); cvmSet(P1cam,1,2, 0); cvmSet(P1cam,1,3, 0);

  cvmSet(P1cam,2,0, 0); cvmSet(P1cam,2,1, 0); cvmSet(P1cam,2,2, 1); cvmSet(P1cam,2,3, 0);

  cvCopy(P, P2cam, 0);


  for (int i = 0; i < 4; ++i) {

    cvmSet(A,0,i, cvmGet(x1,0,0) * cvmGet(P1cam,2,i) - cvmGet(P1cam,0,i));

    cvmSet(A,1,i, cvmGet(x1,1,0) * cvmGet(P1cam,2,i) - cvmGet(P1cam,1,i));

    cvmSet(A,2,i, cvmGet(x2,0,0) * cvmGet(P2cam,2,i) - cvmGet(P2cam,0,i));

    cvmSet(A,3,i, cvmGet(x2,1,0) * cvmGet(P2cam,2,i) - cvmGet(P2cam,1,i));

  }

  cvNormalize(A, Anorm, 1, 0, CV_L2, NULL);

  cvSVD(Anorm, D, U, Vt, CV_SVD_MODIFY_A || CV_SVD_V_T); // A = U D V^T

  double W = cvmGet(Vt,3,3);

  cvmSet(X,0,0, cvmGet(Vt,0,3)/W);

  cvmSet(X,1,0, cvmGet(Vt,1,3)/W);

  cvmSet(X,2,0, cvmGet(Vt,2,3)/W);

}

В OpenCV 2.2 есть функция cvTriangulatePoints для той же цели, но у меня под билдер тока 1.1 и вообще с ней тоже сходу не разберешься...

Буду благодарен любой помощи!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А книжка не Multiple View Geometry ?

Да) Second Edition. Только теперь полная версия)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Dr.Hell В демках OpenCV должен быть пример работы с шахматной доской, вот только с одной камерой.

Используйте справочник OpenCV

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ура, получилось! =) Разобрался с матрицами проекций и все встало на свои места. Сейчас попробую все расписать подробно.

Дано: вебкамера 1 шт, доска шахматная калибровочная 1 шт.

Надо: определить положение соответствующих ключевых точек в 3Д пространстве сцены.

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

Получается следующий алгоритм:

1) Калибруем камеру при помощи доски (этот пример как раз есть в книжке по OpenCV: стандартная связка cvFindChessboardCorners->cvFindCornerSubPix->cvCalibrateCamera2 в гугле по этим функциям находится куча страничек всяких индусов и китайцев, которые перепечатали и успешно откомпилили код из книжки и очень по этому поводу радуются <_< ) - получаем матрицу внутренних параметров камеры (intrinsic) и коэффициенты искажения (distCoeffs). Сохраняем их в xml. Калибровку делаем один раз для одной камеры (если не использовали зум).

2) Используем cvUndistort2 для устранения искажений изображения с камеры.

3) Делаем два снимка, перемещая камеру, из них мы и будем получать наши трехмерные координаты.

4) В функцию cvFindExtrinsicCameraParams2 передаем новые координаты точек доски для первого и второго изображения и внутренние параметры камеры (камера у нас одна, так что параметры одинаковые, будем называть их матрицей K). Получаем rvecs и tvecs - векторы вращения и перемещения для каждого нового положения камеры.

5) Используем cvRodrigues2(rvecs,rmat,NULL); получаем матрицу вращения камеры размерностью 3х3.

До этого пункта мне все было понятно и вчера, проблемы появились дальше.

6) Необходимо получить матрицу проекции P для каждого из двух изображений. По определению m = P*M, где m = [x,y,1]^T - координаты точки на изображении в пикселях, а M = [X,Y,Z]^T - координаты точки в трехмерном пространстве сцены. Так вот, матрица P в том виде, что нам нужна, получается так: P = K*Pcam, где К - матрица внутренних параметров камеры, а Pcam = [rmat | tvecs] размерностью 3х4.

7) Если передать полученные значения в функцию cvTriangulatePoints из OpenCV 2.2, то она вернет вполне корректные координаты точки в трехмерном пространстве сцены.

Я чуть-чуть переписал свою функцию, так что она теперь получает и возвращает такие же параметры, как и cvTriangulatePoints.


//CvMat* projPoints1 = cvCreateMat(2,N,CV_32FC1); // Массив координат точек на первом изображении в пикселях виде матрицы: 

// | x1 x2 ... xN |

// | y1 y2 ... yN |, N - количество точек

//CvMat* projPoints2 = cvCreateMat(2,N,CV_32FC1); // Соответствующие точки:: на втором изображении

//CvMat* projMatr1 = cvCreateMat(3,4,CV_32FC1); //Матрица проекции для первого изображения

//CvMat* projMatr2 = cvCreateMat(3,4,CV_32FC1); //Матрица проекции для второго изображения

//CvMat* points4D = cvCreateMat(4,N,CV_32FC1); // output - получаем массив координат точек в трехмерном пространстве сцены в виде матрицы:

// | X1 X2 ... XN |

// | Y1 Y2 ... YN |

// | Z1 Z2 ... ZN |

// | W1 W2 ... WN |, N - количество точек, W - масштабный множитель или как-то так он называется

void TwoViewTriangulation(CvMat *projMatr1, CvMat *projMatr2, CvMat *projPoints1, CvMat *projPoints2, CvMat *points4D) {

  CvMat* A = cvCreateMat(4,4,CV_64F);

  CvMat* Anorm = cvCreateMat(4,4,CV_64F);

  CvMat* U = cvCreateMat(4,4,CV_64F);

  CvMat* D = cvCreateMat(4,4,CV_64F);

  CvMat* Vt = cvCreateMat(4,4,CV_64F);


  for (int n = 0; n < projPoints1->cols; n++)

  {

      for (int i = 0; i < 4; i++) {

        cvmSet(A,0,i, cvmGet(projPoints1,0,n) * cvmGet(projMatr1,2,i) - cvmGet(projMatr1,0,i));

        cvmSet(A,1,i, cvmGet(projPoints1,1,n) * cvmGet(projMatr1,2,i) - cvmGet(projMatr1,1,i));

        cvmSet(A,2,i, cvmGet(projPoints2,0,n) * cvmGet(projMatr2,2,i) - cvmGet(projMatr2,0,i));

        cvmSet(A,3,i, cvmGet(projPoints2,1,n) * cvmGet(projMatr2,2,i) - cvmGet(projMatr2,1,i));

      }

      cvNormalize(A, Anorm, 1, 0, CV_L2, NULL);

      cvSVD(Anorm, D, U, Vt, CV_SVD_MODIFY_A || CV_SVD_V_T); // A = U D V^T


      cvmSet(points4D,0,n, cvmGet(Vt,0,3));

      cvmSet(points4D,1,n, cvmGet(Vt,1,3));

      cvmSet(points4D,2,n, cvmGet(Vt,2,3));

      cvmSet(points4D,3,n, cvmGet(Vt,3,3));

  }

}

8) Чтобы получить реальные координаты в масштабе сцены, нужно все координаты X, Y, Z разделить на W.

Пока проверил на координатах точек доски, расчетные довольно точно совпадают с реальными (ну, примерно совпадают - уже хорошо :)). Пойду другие ключевые точки доставать и испытывать.

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

post-665-0-41163800-1304697068_thumb.jpg

  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте! Т.е. если у меня есть два изначально откалиброванных изображения, известна ориентация камер, эпиполярные прямые построены, то я могу узнать фокусное расстояние камер и координаты центра камер? Или хотя бы базу стереоскпической системы, т.е. на сколько смещен центр правой камеры относительно центра левой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вот тут попробуйте посмотреть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте! Т.е. если у меня есть два изначально откалиброванных изображения, известна ориентация камер, эпиполярные прямые построены, то я могу узнать фокусное расстояние камер и координаты центра камер? Или хотя бы базу стереоскпической системы, т.е. на сколько смещен центр правой камеры относительно центра левой.

Здравствуйте! Уточните, пожалуйста, какие параметры точно известны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

есть стереоскопическая система, где камеры расположены так, что оси Х коллинеарны, а Y и Z параллельны. из параметров камеры известен только угол камер. ну и что координаты y1=y2 и z1=z2. известны 2D-координаты сопряженных точек

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Из этих параметров мы можем узнать только диспаритет. Нет ни одного параметра, который мог бы хоть как-то зафиксировать размеры системы.

Вот тут для стереопары все очень понятно расписано: http://blog.vidikon.com/?p=176

Изменено пользователем Dr.Hell

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×