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

Доска почета


Popular Content

Showing most liked content on 18.03.2011 во всех областях

  1. 1 point
    целиком. да вроде как оба правильные только 1 будет выглядеть лучше другого, как определить какой лучше хз. первоочередная задача сейчас реализовать RANSAC для тестирования тут два варианта, либо навелосипедить самому или выдрать из opencv ,еще есть вариант с http://web.me.com/dellaert/FrankDellaert/Publications/Entries/2009/7/16_GroupSAC_(ICCV_09).html http://code.google.com/p/groupsac/ ну вот код вообщем то ничего особенного, чем больше HESSIAN тем меньше точек находит. // SURF_test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <cv.h> #include <highgui.h> #define HESSIAN 500 #define FLAG_NUM_DESCR 1 #define RANSAC_ERR 1 #define WITH_VISUAL_TESTS 0 // вывод точек, линий и т.д. для визуальной проверки #define WITH_LINES 1 // с линиями или только точки #define ALL_GREY 0 // только грей или цветные void flannFindPairs( const CvSeq*, const CvSeq* objectDescriptors, const CvSeq*, const CvSeq* imageDescriptors, std::vector<int>& ptpairs ) { int length = (int)(objectDescriptors->elem_size/sizeof(float)); cv::Mat m_object(objectDescriptors->total, length, CV_32F); cv::Mat m_image(imageDescriptors->total, length, CV_32F); // copy descriptors CvSeqReader obj_reader; float* obj_ptr = m_object.ptr<float>(0); cvStartReadSeq( objectDescriptors, &obj_reader ); for(int i = 0; i < objectDescriptors->total; i++ ) { const float* descriptor = (const float*)obj_reader.ptr; CV_NEXT_SEQ_ELEM( obj_reader.seq->elem_size, obj_reader ); memcpy(obj_ptr, descriptor, length*sizeof(float)); obj_ptr += length; } CvSeqReader img_reader; float* img_ptr = m_image.ptr<float>(0); cvStartReadSeq( imageDescriptors, &img_reader ); for(int i = 0; i < imageDescriptors->total; i++ ) { const float* descriptor = (const float*)img_reader.ptr; CV_NEXT_SEQ_ELEM( img_reader.seq->elem_size, img_reader ); memcpy(img_ptr, descriptor, length*sizeof(float)); img_ptr += length; } // find nearest neighbors using FLANN cv::Mat m_indices(objectDescriptors->total, 2, CV_32S); cv::Mat m_dists(objectDescriptors->total, 2, CV_32F); cv::flann::Index flann_index(m_image, cv::flann::KDTreeIndexParams(4)); // using 4 randomized kdtrees flann_index.knnSearch(m_object, m_indices, m_dists, 2, cv::flann::SearchParams(64) ); // maximum number of leafs checked int* indices_ptr = m_indices.ptr<int>(0); float* dists_ptr = m_dists.ptr<float>(0); for (int i=0;i<m_indices.rows;++i) { if (dists_ptr[2*i]<0.6*dists_ptr[2*i+1]) { ptpairs.push_back(i); ptpairs.push_back(indices_ptr[2*i]); } } } int _tmain(int argc, _TCHAR* argv[]) { //TODO //1.сделать консольные параметры //2.глобальная задача подготовить интерфейсы для разных методов(SIFT,SURF,STAR и т.д.)Нахождение точек, нахождение дескрипторов,сравнение дескрипторов разное, а остальное едино. //3.придумать более продуктивный способ выводить точки не загружая изображение, а как то поверх, возможно простой гуй чтобы выбирать\увеличивать область. //4.отдельно реализовать RANSAC или подключить GroupSAC //5.Подправить cvExtractSURF если возможно (жрёт память) //6.если прижмет подправить cvWarpPerspective под очень большие изображения.(разобраться со свопом) //7.разобраться с многопоточностью. //8.возможно перейти на opencv2.2/ //9.сделать обработку для n изображений. //10.вычислить минимальную область достаточную для размещения первого и варпнутого изображения std::string name1= "img1.png"; std::string name2= "img2.png"; IplImage* img1_g = cvLoadImage(name1.c_str(), CV_LOAD_IMAGE_GRAYSCALE); // сразу в грей (потом можно подложить цветные) IplImage* img2_g = cvLoadImage(name2.c_str(), CV_LOAD_IMAGE_GRAYSCALE); int width1=img1_g->width; int height1=img1_g->height; int width2=img2_g->width; int height2=img2_g->height; CvMemStorage* storage = cvCreateMemStorage(0); CvSeq *Keypoints1 = 0, *Descriptors1 = 0; CvSeq *Keypoints2 = 0, *Descriptors2 = 0; CvSURFParams params = cvSURFParams(HESSIAN, FLAG_NUM_DESCR); // параметры по дефолту (500,1) cvExtractSURF( img1_g, 0, &Keypoints1, &Descriptors1, storage, params ); cvExtractSURF( img2_g, 0, &Keypoints2, &Descriptors2, storage, params ); // нахождение пар std::vector<int> ptpairs; //проверить функцию.возможно переписать. flannFindPairs( Keypoints1, Descriptors1, Keypoints2, Descriptors2, ptpairs ); // быстрее чем брутфорсный перебор // функцию не проверял //по хорошему тут сразу же удалить точки которые не попали в пары(если критична память) IplImage* img1; IplImage* img2; int n_channel=0; if (ALL_GREY) { img1=img1_g; img2=img2_g; n_channel=1; } else { cvReleaseImage(&img1_g); cvReleaseImage(&img2_g); img1 = cvLoadImage(name1.c_str()); img2 = cvLoadImage(name2.c_str()); n_channel=img1->nChannels; // оба изображения должны быть цветные //n_channel=3; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (WITH_VISUAL_TESTS) { //тестируем найденные точки (все точки без сопоставлений) // получить из Seq точки CvSURFPoint* point1; for (int i=0;i<Keypoints1->total;i++) { point1=(CvSURFPoint*)cvGetSeqElem(Keypoints1,i); cvCircle(img1, /* the dest image */ cvPoint( cvRound( point1->pt.x), cvRound( point1->pt.y ) ), 2, /* center point and radius */ cvScalar(0, 0, 255, 0), /* the color red */ -1, 8, 0); } cvSaveImage("points1.png", img1); CvSURFPoint* point2; for (int i=0;i<Keypoints2->total;i++) { point2=(CvSURFPoint*)cvGetSeqElem(Keypoints2,i); cvCircle(img2, /* the dest image */ cvPoint( cvRound( point2->pt.x), cvRound( point2->pt.y ) ), 2, /* center point and radius */ cvScalar(255, 0, 0, 0), /* the color blue */ -1, 8, 0); } cvSaveImage("points2.png", img2); //рисуем линии просто для составленных пар //по горизонтали IplImage* img_lines_g=cvCreateImage(cvSize(width1+width2,MAX(height1,height2)),IPL_DEPTH_8U,n_channel); cvSetImageROI(img_lines_g,cvRect(0,0,width1,height1)); cvCopy(img1,img_lines_g); cvSetImageROI(img_lines_g,cvRect(width1,0,width2,height2)); cvCopy(img2,img_lines_g); cvResetImageROI(img_lines_g); for( int i = 0; i < (int)ptpairs.size(); i += 2 ) { CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( Keypoints1, ptpairs[i]); CvSURFPoint* r2 = (CvSURFPoint*)cvGetSeqElem( Keypoints2, ptpairs[i+1] ); cvLine( img_lines_g, cvPoint(r1->pt.x,r1->pt.y ), cvPoint(width1+r2->pt.x, r2->pt.y ), cvScalar(0, 255, 255, 0) ,1,CV_AA); } cvSaveImage("lines_g.png", img_lines_g); cvReleaseImage(&img_lines_g); //по вертикали IplImage* img_lines_v=cvCreateImage(cvSize(MAX(width1,width2),height1+height2),IPL_DEPTH_8U,n_channel); cvSetImageROI(img_lines_v,cvRect(0,0,width1,height1)); cvCopy(img1,img_lines_v); cvSetImageROI(img_lines_v,cvRect(0,height1,width2,height2)); cvCopy(img2,img_lines_v); cvResetImageROI(img_lines_v); for( int i = 0; i < (int)ptpairs.size(); i += 2 ) { CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( Keypoints1, ptpairs[i]); CvSURFPoint* r2 = (CvSURFPoint*)cvGetSeqElem( Keypoints2, ptpairs[i+1] ); cvLine( img_lines_v, cvPoint(r1->pt.x,r1->pt.y ), cvPoint(r2->pt.x, height1+r2->pt.y ), cvScalar(255, 255, 0, 0) ,1,CV_AA); } cvSaveImage("lines_v.png", img_lines_v); cvReleaseImage(&img_lines_v); //подсветка пар точек (без и с линиями) с выводом //по горизонтали IplImage* img_pairs_g=cvCreateImage(cvSize(width1+width2,MAX(height1,height2)),IPL_DEPTH_8U,n_channel); cvSetImageROI(img_pairs_g,cvRect(0,0,width1,height1)); cvCopy(img1,img_pairs_g); cvSetImageROI(img_pairs_g,cvRect(width1,0,width2,height2)); cvCopy(img2,img_pairs_g); cvResetImageROI(img_pairs_g); cvNamedWindow( "lines_g", 0); cvShowImage( "lines_g", img_pairs_g); for(int i=0; { int key=cvWaitKey(0); if (key==27) //esс break; else { if (key ==2490368) //стрелка вверх { i+=2; } if (key ==2621440) //стрелка вниз { i-=2; } if (((int)ptpairs.size()-2)<i) i=0; if (i<0) i=(int)ptpairs.size()-2; CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( Keypoints1, ptpairs[i]); CvSURFPoint* r2 = (CvSURFPoint*)cvGetSeqElem( Keypoints2, ptpairs[i+1] ); cvCircle(img_pairs_g, cvPoint(r1->pt.x,r1->pt.y), 4, cvScalar(0, 255, 255, 0), -1, 8, 0); cvCircle(img_pairs_g, cvPoint(width1+r2->pt.x, r2->pt.y), 4, cvScalar(0, 255, 255, 0), -1, 8, 0); if (WITH_LINES) { cvLine( img_pairs_g, cvPoint(r1->pt.x,r1->pt.y ), cvPoint(width1+r2->pt.x, r2->pt.y ), cvScalar(0, 255, 255, 0) ,1,CV_AA); } //для больших ихображений будет тормозить cvShowImage( "lines_g", img_pairs_g);//придумать более продуктивный способ выводить точки не загружая изображение, а как то поверх. } } cvReleaseImage(&img_pairs_g); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //считаем матрицу гомографии int c_point_count = ((int)ptpairs.size())/2; CvMat* points1 = cvCreateMat(2, c_point_count, CV_32FC1); CvMat* points2 = cvCreateMat(2, c_point_count, CV_32FC1); for( int i = 0; i < (int)ptpairs.size(); i += 2) { CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( Keypoints1, ptpairs[i]); CvSURFPoint* r2 = (CvSURFPoint*)cvGetSeqElem( Keypoints2, ptpairs[i+1]); cvmSet(points1,0,i/2,r1->pt.x); cvmSet(points1,1,i/2,r1->pt.y); cvmSet(points2,0,i/2,r2->pt.x); cvmSet(points2,1,i/2,r2->pt.y); } CvMat* homography_matrix = cvCreateMat(3, 3, CV_32FC1); cvFindHomography(points2, points1, homography_matrix, CV_RANSAC, RANSAC_ERR); //cvFindHomography(points1, points2, homography_matrix, CV_RANSAC, RANSAC_ERR);// матрица наоборот? //вся матрица гомографии int m11=CV_MAT_ELEM( *homography_matrix, float, 0, 0 );// int m12=CV_MAT_ELEM( *homography_matrix, float, 0, 1 );// int m13=CV_MAT_ELEM( *homography_matrix, float, 0, 2 );//сдвиг по х int m21=CV_MAT_ELEM( *homography_matrix, float, 1, 0 );// int m22=CV_MAT_ELEM( *homography_matrix, float, 1, 1 );// int m23=CV_MAT_ELEM( *homography_matrix, float, 1, 2 );//сдвиг по у int m31=CV_MAT_ELEM( *homography_matrix, float, 2, 0 );// int m32=CV_MAT_ELEM( *homography_matrix, float, 2, 1 );// int m33=CV_MAT_ELEM( *homography_matrix, float, 2, 2 );// //вопрос в том что накладывается сверху? как определить лучший вариант(более глубокий вопрос это выбор нелинейной области перекрытия + сглаживание) IplImage* img_out=cvCreateImage(cvSize(width1+width2,height1+height2),IPL_DEPTH_8U,n_channel); // максимальный размер //IplImage* img_out=cvCreateImage(cvSize(m13+width2,m23+height2),IPL_DEPTH_8U,n_channel); // попытка выделить минимальный необходимый размер cvWarpPerspective(img2,img_out,homography_matrix,CV_WARP_FILL_OUTLIERS,cvScalarAll(0)); cvSetImageROI(img_out,cvRect(0,0,width1,height1)); cvCopy(img1,img_out); cvResetImageROI(img_out); cvSaveImage("out.png", img_out); //конец. удаляем все cvReleaseImage(&img1); cvReleaseImage(&img2); //удалить точки и дескрипторы (правильно через cvClearSeq или через cvReleaseMemStorage или cvClearMemStorage?) cvClearSeq(Keypoints1); cvClearSeq(Keypoints2); cvClearSeq(Descriptors1); cvClearSeq(Descriptors2); cvClearMemStorage(storage); cvReleaseMemStorage(&storage); // вроде бы достаточно только этого вместо cvClearSeq и cvClearMemStorage return 0; }[/code]
×