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

Dr.Hell

Пользователи
  • Количество публикаций

    17
  • Зарегистрирован

  • Посещение

  • Days Won

    2

Все публикации пользователя Dr.Hell

  1. Работа с камерами

    У меня были две одинаковые вебки от sony 2001 года выпуска, и они никак не хотели вместе работать, работала только та, которую первую подключили. Так что, тут не угадаешь, какие две будут работать, а какие нет. В итоге купил вот такую камеру: http://roboforum.ru/forum36/topic1350-45.html#p214256 Вообще я в камерах совсем не разбираюсь, даже не знал, что в некоторых бывает ик-фильтр.
  2. OpenCV 2.3

    Сегодня вышла финальная версия 2.3: http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.3/ Список изменений тут: http://opencv.willowgarage.com/wiki/OpenCV%20Change%20Logs Лично меня в списке изменения порадовала возможность калибровки по новому шаблону с кружками. Обещают, что точность возрастет. Надеюсь, что так. =) Кто-нибудь собирается ставить?
  3. Пишу приложение в BCB с компонентом TCppWebBrowser, как только в коде появляется хоть одна функция из highgui, приложение сразу при запуске (собственно при создании компонента TCppWebBrowser) вылетает с ошибкой "Could not obtain OLE control window handle". UPD: При запуске программы форма, на которой лежат компоненты, не появляется, а окно браузера появляется одно само по себе (и сразу вылезает ошибка). То есть, highgui каким-то образом переиначивает главное окно программы.
  4. В общем, забил я на эту проблему. При особой надобности можно без проблем вызвать внешнее окно IE, и с ним работать точно так же, как со встроенным браузером. #include "mshtml.h" #include "exdisp.h" #pragma link "SHDocVw_OCX" HRESULT hr = S_OK; Shdocvw_tlb::IWebBrowser2 * iBrowser = NULL; hr = CoCreateInstance( CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, Shdocvw_tlb::IID_IWebBrowser2, (LPVOID*)&iBrowser); if (hr != S_OK) { ShowMessage ("Error creating the IWebBrowser2"); return; } iBrowser->Visible = true; iBrowser->Navigate("http://lozhki.net");
  5. Конкретно вызываю cvCreateVideoWriter, но ошибка позникает и с cvCaptureFromCAM, и просто с cvSaveImage. Появление ошибки зависит не от того, вызываю ли я эту функцию, а от того, компилится код с ее вызовом или без. Провел эксперимент. Повесил на одну кнопку создание новой формы, а на другую - создание веббраузера на ней. CppWebBrowser1 = new TCppWebBrowser(Form2); CppWebBrowser1->TControl::Parent = Form2; Если компилю без cvCreateVideoWriter, то все нормально, нажимаю на первую кнопку - появляется форма, нажимаю на вторую, появляется браузер на этой форме. Если компилю с cvCreateVideoWriter (просто добавляю вызов этой функции в любое место кода), то при нажатии на первую кнопку тоже нормально появляется форма, а при нажатии на вторую браузер появляется не на форме, а в левом верхнем углу экрана. Сабжевая ошибка вылезает на строчке CppWebBrowser1->TControl::Parent = Form2;
  6. HBITMAP to IplImage*

    Вот тут очень простой пример, как сохранить снимок экрана в IplImage через TBitmap: http://www.compvision.ru/forum/index.php?showtopic=538&view=findpost&p=3340
  7. Здравствуйте! Программа на Borland Builder. Есть hDC компонента, нужно его изображение скопировать в IplImage. То есть, необходима функция обратная APIDrawIpl. Понятно, что скорее всего нужно аналогично побитово скопировать Bitmap в ImageData (хотя, тоже не очень понятно, как это сделать). Но может быть, есть какой-то более быстрый и легкий путь в эту сторону? Нашел вот эту тему: http://www.compvision.ru/forum/index.php?showtopic=390 Но, честно говоря, не понял, какое решение в итоге рабочее.
  8. Спасибо! =) Оказалось, все вообще элементарно! И, главное, работает просто молниеносно, что мне и было необходимо! IplImage * TBitmapToIplImage(Graphics::TBitmap *src) { int _h = src->Height; int _w = src->Width; if (!src || _w==0) return NULL; IplImage* dest = cvCreateImage(cvSize(_w,_h),IPL_DEPTH_8U,3); try { unsigned char *pLine; for(int y=0; y<_h; y++) { pLine = (unsigned char *)src->ScanLine[y]; memcpy(dest->imageData+_w*3*y, pLine, _w*3); } } catch(...) { MessageBox(0,"Exception when get data ","Error", MB_OK ); } return dest; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Graphics::TBitmap* Bitmap = new Graphics::TBitmap; HDC DC=GetDC(0); // Делаем снимок экрана для примера, тут можно использовать любой DC try{ Bitmap->Height=Screen->Height; Bitmap->Width=Screen->Width; Bitmap->PixelFormat=pf24bit; // Обязательно нужно перевести в 24 бита // Копируем DC в битмап BitBlt(Bitmap->Canvas->Handle, 0, 0, Screen->Width, Screen->Height,DC, 0, 0, SRCCOPY); IplImage* TestImage = TBitmapToIplImage(Bitmap); APIDrawIpl(0,0,TestImage,Form1->Handle); } __finally { delete Bitmap; ReleaseDC(0,DC); } }
  9. У меня программа вылетала с ошибкой "divizion by zero" на строчке: if( !cvFindHomography( &_pt1, &_pt2, &_h, CV_RANSAC, 5 )) Стал искать причину, обнаружил, что функция naiveNearestNeighbor может возвращать одну и ту же точку сколько угодно раз. То есть, для примера, у нас найдено n особенностей для исходного изображения и 1 особенность для изображения с камеры, тогда эта одна точка почему-то будет считаться парой для всех n точек из шаблона. Скорее всего функция naiveNearestNeighbor не очень верно работает (я с ней особо не разбирался), возможно, необходимо добавить туда еще какой-то порог или изменить существующие параметры. Добавил в функцию findPairs вот такую заглушку: if( nearest_neighbor >= 0 && nearest_neighbor != last_neighbor) { ptpairs.push_back(i); ptpairs.push_back(nearest_neighbor); last_neighbor = nearest_neighbor; } Хотя, все равно иногда вылетает та же ошибка (может быть это проблема борландовского компилятора), так что надо туда просто повесить обработчик ошибок и забить. На всякий случай прикрепляю проект для borland builder 6, вдруг кому-то пригодится. OpenCV SURF.rar
  10. Здравствуйте! Помогите пожалуйста откомпилить этот код в bcb6. http://www.compvision.ru/forum/index.php?showtopic=103&view=findpost&p=562 Почему-то вылезает ошибка "LIBJASPER.DLL не был найден" в момент выполнения ptpairs.clear() и других операций с векторами (связи не вижу никакой между vector.h и libjasper.dll). Работаю с OpenCV1.1pre, в других OpenCV приложениях, где не использую вектора, никаких проблем нет.
  11. Ошибка "LIBJASPER.DLL не был найден"

    Оу, че-то я стромозил. Видел тему, в которой это было написано, пробовал удалять .lib файлы - не помогло. А то, что они подключены к проекту, вообще выпало из головы. Сделал Remove from project - заработало! Спасибо! =)
  12. Триангуляция

    Тоже очень интересует этот вопрос. Вот тут вроде бы расписано, а все равно нифига не понятно... http://www.wiziq.com/tutorial/20171-feb-21-lecture-one-Algorithms-in-Geometry-and-Topo Задача усложняется тем, что Convex Hull 3D делает вместо модели "подарочную упаковку" (пример с зайцем отсюда), то есть подходит только для совсем выпуклых моделей без выступающих частей. А триангуляция Делоне соединяет вообще все точки, даже те, которые находятся внутри предполагаемой модели, а в итоге тоже получается "подарочная упаковка", да еще и с кучей вершин внутри. Единственный вариант, который на мой взгляд будет давать хорошие результаты, это когда у нас облако точек представляет собой частую сетку с фиксированным шагом, тогда можно соединять соседние точки, проверяя их критерием Делоне.
  13. Из этих параметров мы можем узнать только диспаритет. Нет ни одного параметра, который мог бы хоть как-то зафиксировать размеры системы. Вот тут для стереопары все очень понятно расписано: http://blog.vidikon.com/?p=176
  14. Здравствуйте! Уточните, пожалуйста, какие параметры точно известны.
  15. Ура, получилось! =) Разобрался с матрицами проекций и все встало на свои места. Сейчас попробую все расписать подробно. Дано: вебкамера 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. Пока проверил на координатах точек доски, расчетные довольно точно совпадают с реальными (ну, примерно совпадают - уже хорошо ). Пойду другие ключевые точки доставать и испытывать. Как только напишу функцию, которая из фундаментальной матрицы получает корректные матрицы проекций для камеры, то доска больше будет не нужна. Обязательно сюда тогда добавлю.
  16. Чуть-чуть не в тему, на калибровку я забил пока, калибрую по доске, оттуда же беру матрицы трансформации. Не получается из соответствующих точек на двух изображениях получить 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 и вообще с ней тоже сходу не разберешься... Буду благодарен любой помощи!
  17. Всем, привет! =) Ну как, в итоге что-нибудь получилось?
×