Nuzhny 243 Report post Posted January 28, 2011 Кстати. В gimp'е есть фильтр "убрать искажение оптики". Там несколько движков, передвигая которые можно убирать дисторсию. В автоматическом режиме такое работать не будет, но можно один раз настроить для конкретной камеры, если она стационарная. Ещё есть убирание дисторсии в проекте с открытыми исходниками IVT. Пример называется UndistortionRectificationDemo. В этом же примере есть "выпрямление" изображения, если оно снималось под наклоном. Share this post Link to post Share on other sites
Игорь 0 Report post Posted January 28, 2011 Ещё есть убирание дисторсии в проекте с открытыми исходниками IVT. Пример называется UndistortionRectificationDemo. В этом же примере есть "выпрямление" изображения, если оно снималось под наклоном. Можна вопрос??? Не могу понять что-это за ресурс IVT. Это еще ожни библиотеки, че-то наподобе ОпенСв... Или я ошибаюсь... Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted January 28, 2011 Не ошибаешься. Share this post Link to post Share on other sites
Игорь 0 Report post Posted January 28, 2011 Не ошибаешься. А какой из этих вариантов тогда выходит лучше!!!! OpenCV или IVT???? или это дело выбора??? Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted January 28, 2011 Что тебе на текущий момент больше подходит, то и выбирай. OpenCV хорошая, но неидеальная библиотека. Ну и никто не запрещает использовать и то, и другое одновременно. Share this post Link to post Share on other sites
Игорь 0 Report post Posted January 31, 2011 Что тебе на текущий момент больше подходит, то и выбирай. OpenCV хорошая, но неидеальная библиотека. Ну и никто не запрещает использовать и то, и другое одновременно. Спасибо за инфу!!!!!! Share this post Link to post Share on other sites
Dr.Hell 5 Report post Posted April 9, 2011 Всем, привет! =) Ну как, в итоге что-нибудь получилось? Share this post Link to post Share on other sites
FreeGOD 0 Report post Posted April 9, 2011 Я как-то писал: С эпиполярными линиями все понятно, все работает почти при любых позициях камер. Так вот... При любых позициях все работает, но проблема в самих точках. Они должны быть на одной плоскости. Чем больше отклонение от плоскости, тем хуже находит эпиполярные линии. До того как я это узнал, прошло много времени. Потом я попытался всё сделать по-другому, составил громадную систему уравнений, там остаются неизвестные. Недавно нашел одну хорошую книгу на Английском, пробежался по картинкам, но еще не читал. На этом пока остановился. Не хватает времени и идей. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted April 9, 2011 А книжка не Multiple View Geometry ? Share this post Link to post Share on other sites
Dr.Hell 5 Report post Posted May 5, 2011 Чуть-чуть не в тему, на калибровку я забил пока, калибрую по доске, оттуда же беру матрицы трансформации. Не получается из соответствующих точек на двух изображениях получить 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 и вообще с ней тоже сходу не разберешься... Буду благодарен любой помощи! Share this post Link to post Share on other sites
FreeGOD 0 Report post Posted May 5, 2011 А книжка не Multiple View Geometry ? Да) Second Edition. Только теперь полная версия) Share this post Link to post Share on other sites
FreeGOD 0 Report post Posted May 5, 2011 Dr.Hell В демках OpenCV должен быть пример работы с шахматной доской, вот только с одной камерой. Используйте справочник OpenCV Share this post Link to post Share on other sites
Dr.Hell 5 Report post Posted May 6, 2011 Ура, получилось! =) Разобрался с матрицами проекций и все встало на свои места. Сейчас попробую все расписать подробно. Дано: вебкамера 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. Пока проверил на координатах точек доски, расчетные довольно точно совпадают с реальными (ну, примерно совпадают - уже хорошо ). Пойду другие ключевые точки доставать и испытывать. Как только напишу функцию, которая из фундаментальной матрицы получает корректные матрицы проекций для камеры, то доска больше будет не нужна. Обязательно сюда тогда добавлю. 2 Share this post Link to post Share on other sites
zaza 0 Report post Posted May 7, 2011 Здравствуйте! Т.е. если у меня есть два изначально откалиброванных изображения, известна ориентация камер, эпиполярные прямые построены, то я могу узнать фокусное расстояние камер и координаты центра камер? Или хотя бы базу стереоскпической системы, т.е. на сколько смещен центр правой камеры относительно центра левой. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted May 7, 2011 Вот тут попробуйте посмотреть. Share this post Link to post Share on other sites
Dr.Hell 5 Report post Posted May 8, 2011 Здравствуйте! Т.е. если у меня есть два изначально откалиброванных изображения, известна ориентация камер, эпиполярные прямые построены, то я могу узнать фокусное расстояние камер и координаты центра камер? Или хотя бы базу стереоскпической системы, т.е. на сколько смещен центр правой камеры относительно центра левой. Здравствуйте! Уточните, пожалуйста, какие параметры точно известны. Share this post Link to post Share on other sites
zaza 0 Report post Posted May 8, 2011 есть стереоскопическая система, где камеры расположены так, что оси Х коллинеарны, а Y и Z параллельны. из параметров камеры известен только угол камер. ну и что координаты y1=y2 и z1=z2. известны 2D-координаты сопряженных точек Share this post Link to post Share on other sites
Dr.Hell 5 Report post Posted May 8, 2011 (edited) Из этих параметров мы можем узнать только диспаритет. Нет ни одного параметра, который мог бы хоть как-то зафиксировать размеры системы. Вот тут для стереопары все очень понятно расписано: http://blog.vidikon.com/?p=176 Edited May 8, 2011 by Dr.Hell Share this post Link to post Share on other sites
dasg 1 Report post Posted June 29, 2011 Готовая калибровка на OpenCV с описанием есть на сайте http://robot-develop.org/archives/2026. Share this post Link to post Share on other sites
dasg 1 Report post Posted June 29, 2011 Есть описание параметров, получаемых при калибровке вот здесь: http://robot-develop.org/archives/2026. 1 Share this post Link to post Share on other sites
Nuzhny 243 Report post Posted June 29, 2011 В недавно вышедшей версии OpenCV 2.3 появилась возможность калибровки не по шахматной доске, а по кругам. Вроде, точнее получается. Share this post Link to post Share on other sites