Jump to content
Compvision.ru
TroyashkA

Проблемы с ExtractSURF() и CvMemStorage

Recommended Posts

ну тут вопрос возможно ли распараллеливание SURF (что эквивалентно ответу на вопрос можно ли делить изображение на куски)

http://www.vision.ee.ethz.ch/~surf/eccv06.pdf надо как бы понять сам алгоритм.

SIFT походу вообще нельзя делить т.к. там строятся пирамиды от начального изображения (хотя я может и ошибаюсь).

а так то пусть 1Гб занято системой на всякую лабуду,

загружаем 1 изображение ~1Гб находим точки + N мб (зависит от длины вектора дескрипторов и количества точек)

удаляем 1 изображения -1Гб

загружаем 2 изображение (все тоже самое)

удаляем 2 изображение

имеем (N1+N2)мб точек+дескрипторы. фильтруем с помощью flannFindPairs.

удаляем все остальные точки, имеем Nмб точек.

пихаем все добро в cvFindHomography там RANSAC'ом фильтруется.

(кстати хотелось бы получить его отдельную реализацию, а то он встроен cvFindHomography , а внутренний код я не осилил и сам написать тоже не осилил)

(и еще вопрос когда надо использовать матрицу гомографии, а когда фундаментальную матрицу)

удаляем все точки.имеем только матрицу гомографии.

загружем 2 изображения ~2Гб и делаем cvWarpPerspective (для варпа полюбому надо загружать все изображения или писать что то свое)

в итоге за 4 гб вроде и не вышли.

другое дело если это какие то замуты в opencv ограничение на кол-во точек и используемую суммарную память. (вроде в винде х32 приложение может использовать макс 2Гб с расширением (какой то там ключ) вроде бы 3Гб)

Share this post


Link to post
Share on other sites

ну тут вопрос возможно ли распараллеливание SURF (что эквивалентно ответу на вопрос можно ли делить изображение на куски)

http://www.vision.ee.ethz.ch/~surf/eccv06.pdf надо как бы понять сам алгоритм.

SIFT походу вообще нельзя делить т.к. там строятся пирамиды от начального изображения (хотя я может и ошибаюсь).

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

а так то пусть 1Гб занято системой на всякую лабуду,

загружаем 1 изображение ~1Гб находим точки + N мб (зависит от длины вектора дескрипторов и количества точек)

удаляем 1 изображения -1Гб

загружаем 2 изображение (все тоже самое)

удаляем 2 изображение

имеем (N1+N2)мб точек+дескрипторы. фильтруем с помощью flannFindPairs.

удаляем все остальные точки, имеем Nмб точек.

пихаем все добро в cvFindHomography там RANSAC'ом фильтруется.

Важно понимать, что у нас есть такая замечательная вещь, как виртуальная память, там мы можем хранить большие объемы и не обязательно пихать все в ОЗУ :)

(кстати хотелось бы получить его отдельную реализацию, а то он встроен cvFindHomography , а внутренний код я не осилил и сам написать тоже не осилил)

(и еще вопрос когда надо использовать матрицу гомографии, а когда фундаментальную матрицу)

удаляем все точки.имеем только матрицу гомографии.

загружем 2 изображения ~2Гб и делаем cvWarpPerspective (для варпа полюбому надо загружать все изображения или писать что то свое)

Да, насчет RANSAC вы правы - я тоже хотел бы отдельно. Также не знаю ответа на вопрос "когда надо использовать матрицу гомографии, а когда фундаментальную матрицу". И конечно то, о чем я тоже задумывался - как "скормить" всё изображение (мы подаем только одно изображение, а не два) функции cvWarpPerspective() ...

Share this post


Link to post
Share on other sites
Думаю, что можно распараллелить не сам алгоритм, а именно выделение ключевых особенностей из тайлов изображения.

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

Важно понимать, что у нас есть такая замечательная вещь, как виртуальная память, там мы можем хранить большие объемы и не обязательно пихать все в ОЗУ

ну если винда сделает все сама на автомате то хорошо, но скорее всего об этом надо самому заботится.

(мы подаем только одно изображение, а не два) функции cvWarpPerspective()

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

т.е. на первом шаге 1+(1-per1)

на втором 1+(1-per1)+(1-per2)

на N шаге 1+(1-per1)+(1-per2)+..+(1-perN)

где perN процент перекрытия изображений на N шаге.

Share this post


Link to post
Share on other sites

хмм посмотрел что происходит в диспетчере задач, когда доходит дело до cvExtractSURF , так там резкое выделение памяти где то 1.5 гига, вообще то странно, учитывая, что потом то все освобождается (т.е. это не дескрипторы столько занимают) по F10 не удалось войти в функцию возможно потому что она в скомпиленой либе?

там по ходу алгоритм такой находят много много точек, а потом по параметру HESSIAN выкидывают лишние.

еще не совсем ясное дело с cvWarpPerspective получается, что возможно наложить только первое нетронутое изображение на варпнутое? т.е. я не понял можно ли выбирать какое изображение будет сверху и какое варпиться относительно какого?


CvMat* homography_matrix = cvCreateMat(3, 3, CV_32FC1); 

cvFindHomography(points2, points1, homography_matrix, CV_RANSAC, RANSAC_ERR); // возможно переставлять points1 и points2 местами?

IplImage* img_rgb1 = cvLoadImage("1.bmp");

IplImage* img_rgb2 = cvLoadImage("2.bmp");

IplImage* img_warp=cvCreateImage(cvSize(img_rgb1->width+img_rgb2->width,img_rgb1->height+img_rgb2->height),IPL_DEPTH_8U,3);

cvWarpPerspective(img_rgb2,img_warp,homography_matrix,CV_WARP_FILL_OUTLIERS,cvScalarAll(0));

cvSetImageROI(img_warp,cvRect(0,0,img_rgb1->width,img_rgb1->height));

cvCopy(img_rgb1,img_warp);

cvResetImageROI(img_warp);

в итоге у меня удачно получилось склеить два снимка которые вы выкладывали, они правда 30-40 мб и в размере 5кх7к

Share this post


Link to post
Share on other sites

хмм посмотрел что происходит в диспетчере задач, когда доходит дело до cvExtractSURF , так там резкое выделение памяти где то 1.5 гига, вообще то странно, учитывая, что потом то все освобождается (т.е. это не дескрипторы столько занимают) по F10 не удалось войти в функцию возможно потому что она в скомпиленой либе?

там по ходу алгоритм такой находят много много точек, а потом по параметру HESSIAN выкидывают лишние.

Какой размер тайла Вы ставите?

еще не совсем ясное дело с cvWarpPerspective получается, что возможно наложить только первое нетронутое изображение на варпнутое? т.е. я не понял можно ли выбирать какое изображение будет сверху и какое варпиться относительно какого?

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


CvMat* homography_matrix = cvCreateMat(3, 3, CV_32FC1); 

cvFindHomography(points2, points1, homography_matrix, CV_RANSAC, RANSAC_ERR); // возможно переставлять points1 и points2 местами?

IplImage* img_rgb1 = cvLoadImage("1.bmp");

IplImage* img_rgb2 = cvLoadImage("2.bmp");

IplImage* img_warp=cvCreateImage(cvSize(img_rgb1->width+img_rgb2->width,img_rgb1->height+img_rgb2->height),IPL_DEPTH_8U,3);

cvWarpPerspective(img_rgb2,img_warp,homography_matrix,CV_WARP_FILL_OUTLIERS,cvScalarAll(0));

cvSetImageROI(img_warp,cvRect(0,0,img_rgb1->width,img_rgb1->height));

cvCopy(img_rgb1,img_warp);

cvResetImageROI(img_warp);

в итоге у меня удачно получилось склеить два снимка которые вы выкладывали, они правда 30-40 мб и в размере 5кх7к

Массивы точек переставлять не надо, а то угол поворота у изображения будет наоборот.

Скиньте весь код, если не затруднит.

Share this post


Link to post
Share on other sites
Какой размер тайла Вы ставите?

целиком.

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

да вроде как оба правильные только 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]

  • Like 1

Share this post


Link to post
Share on other sites

так я про них и говорил.

У меня уже вот этот код дает ошибку, описанную выше (не хватает памяти):


objectGray = cvLoadImage("D:\\IMGS\\LANSAT\\1.bmp", CV_LOAD_IMAGE_GRAYSCALE );

imageGray = cvLoadImage("D:\\IMGS\\LANSAT\\2.bmp", CV_LOAD_IMAGE_GRAYSCALE );


CvMemStorage* storage = cvCreateMemStorage(0);

CvSeq *keys1 = 0, *desc1 = 0;

CvSeq *keys2 = 0, *desc2 = 0;

CvSURFParams paramz = cvSURFParams(500, 1);

cvExtractSURF( objectGray, 0, &keys1, &desc1, storage, paramz);

cvExtractSURF( imageGray, 0, &keys2, &desc2, storage, paramz);

Версия библиотеки OpenCV2.2

Share this post


Link to post
Share on other sites

ну так наверно из-за cvExtractSURF

HESSIAN поставьте 6000 вместо 500 например и попробуйте так.

хотя у меня и с 500 работало на opencv2.1 (хотя думаю это не влияет)

Share this post


Link to post
Share on other sites

ну так наверно из-за cvExtractSURF

HESSIAN поставьте 6000 вместо 500 например и попробуйте так.

хотя у меня и с 500 работало на opencv2.1 (хотя думаю это не влияет)

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

Share this post


Link to post
Share on other sites

http://opencv.willowgarage.com/documentation/dynamic_structures.html#cvseq

ну чтение из cvSeq вроде так

(desrcriptor->first)->data; // 1 элемент последовательности

((desrcriptor->first)->h_next)->data; // 2 элемент последовательности

только как там эта инфа хранится я не знаю.

и еще я flannFindPairs не проверял и не разбирался взял из каких то примеров. там как раз чтение и сравнение дескрипторов.

а cvExtractSURF надо внутрь лезть смотреть где там выделения памяти такое сильное, но чо то по F10 у меня в функцию не заходит при дебаге(может просто не компилить библиотеку, а тупо подключить сорцы? тогда можно будет и функцию править и при дебаге смотреть)

Share this post


Link to post
Share on other sites

http://opencv.willowgarage.com/documentation/dynamic_structures.html#cvseq

ну чтение из cvSeq вроде так

(desrcriptor->first)->data; // 1 элемент последовательности

((desrcriptor->first)->h_next)->data; // 2 элемент последовательности

только как там эта инфа хранится я не знаю.

и еще я flannFindPairs не проверял и не разбирался взял из каких то примеров. там как раз чтение и сравнение дескрипторов.

а cvExtractSURF надо внутрь лезть смотреть где там выделения памяти такое сильное, но чо то по F10 у меня в функцию не заходит при дебаге(может просто не компилить библиотеку, а тупо подключить сорцы? тогда можно будет и функцию править и при дебаге смотреть)

flannFindPairs() глянул мельком. А вот насчет того, чтобы править саму OpenCV у меня опыта маловато :)

А я сейчас другой задачей занимаюсь - пытаюсь открыть большое изображение (~1GB) по частям и потом скормить части cvSetImageData() ...

Share this post


Link to post
Share on other sites

хмм IplImage* img= cvCreateImage(cvSize(20000,20000), IPL_DEPTH_8U, 3); так работает, а если ,30к х 30к то уже ошибка.

http://tech.groups.yahoo.com/group/OpenCV/message/55861

тут пишут что может это из-за фрагментации памяти, и надо поправить CV_MAX_ALLOC_SIZE.

Share this post


Link to post
Share on other sites

хмм IplImage* img= cvCreateImage(cvSize(20000,20000), IPL_DEPTH_8U, 3); так работает, а если ,30к х 30к то уже ошибка.

http://tech.groups.yahoo.com/group/OpenCV/message/55861

тут пишут что может это из-за фрагментации памяти, и надо поправить CV_MAX_ALLOC_SIZE.

Хм ... возможно это понадобится для cvWarpPerspective(), хотя есть задумка, как обойти проблему - не знаю правильно ли это будет работать, но на крайний случай буду пытаться менять CV_MAX_ALLOC_SIZE и перекомпилировать библиотеку.

Share this post


Link to post
Share on other sites

CV_MAX_ALLOC_SIZE я нашел только в cxmisc.h

но чо то сакрального смысла я не понял)

ну там действительно какие то настройки.

/* maximum size of dynamic memory buffer.

   cvAlloc reports an error if a larger block is requested. */

#define  CV_MAX_ALLOC_SIZE    (((size_t)1 << (sizeof(size_t)*8-2)))
а может это надо менять
/* maximal size of local memory storage */

#define  CV_MAX_LOCAL_SIZE  \

    (CV_MAX_LOCAL_MAT_SIZE*CV_MAX_LOCAL_MAT_SIZE*(int)sizeof(double))
cvWarpPerspective() наверно можно и по кускам. Если имеем матрицу гомографии H, то левый верхний варпим по ней, а остальные со смещением относительно левого верхнего.(но надо проверить)
int m13=CV_MAT_ELEM( *homography_matrix, float, 0, 2 );//сдвиг по х

 int m23=CV_MAT_ELEM( *homography_matrix, float, 1, 2 );//сдвиг по у

как определить наклон сторон прямоугольника я пока не понял.

Share this post


Link to post
Share on other sites

CV_MAX_ALLOC_SIZE я нашел только в cxmisc.h

но чо то сакрального смысла я не понял)

ну там действительно какие то настройки.

/* maximum size of dynamic memory buffer.

   cvAlloc reports an error if a larger block is requested. */

#define  CV_MAX_ALLOC_SIZE    (((size_t)1 << (sizeof(size_t)*8-2)))
а может это надо менять
/* maximal size of local memory storage */

#define  CV_MAX_LOCAL_SIZE  \

    (CV_MAX_LOCAL_MAT_SIZE*CV_MAX_LOCAL_MAT_SIZE*(int)sizeof(double))
cvWarpPerspective() наверно можно и по кускам. Если имеем матрицу гомографии H, то левый верхний варпим по ней, а остальные со смещением относительно левого верхнего.(но надо проверить)
int m13=CV_MAT_ELEM( *homography_matrix, float, 0, 2 );//сдвиг по х

 int m23=CV_MAT_ELEM( *homography_matrix, float, 1, 2 );//сдвиг по у

как определить наклон сторон прямоугольника я пока не понял.

Насчет CV_MAX_ALLOC_SIZE я тоже не понял, где менять и что. А угол поворота всегда можно узнать, если у нас известны координаты углов.

Share this post


Link to post
Share on other sites

(((size_t)1 << (sizeof(size_t)*8-2)))

sizeof(size_t)=32 бита на х32(64 на х64) , 254 (510) бит. чо то до гб как то далековато.

что значит оператор << в данном контексте я вообще не понял.

А угол поворота всегда можно узнать, если у нас известны координаты углов.

нам известна матрица гомографии, и как из не получить координаты углов?

Share this post


Link to post
Share on other sites

(((size_t)1 << (sizeof(size_t)*8-2)))

sizeof(size_t)=32 бита на х32(64 на х64) , 254 (510) бит. чо то до гб как то далековато.

что значит оператор << в данном контексте я вообще не понял.

Оператор << это оператор сдвига влево (в гугле есть инфа)

нам известна матрица гомографии, и как из не получить координаты углов?


void GetCorners()

{

	CvPoint src_corners[4] = {

		{0, 0},

		{object->width, 0},

		{object->width, object->height},

		{0, object->height}

	};


	double h[9];

	h[0] = cvmGet(homo, 0, 0); h[1] = cvmGet(homo, 0, 1); h[2] = cvmGet(homo, 0, 2);

	h[3] = cvmGet(homo, 1, 0); h[4] = cvmGet(homo, 1, 1); h[5] = cvmGet(homo, 1, 2);

	h[6] = cvmGet(homo, 2, 0); h[7] = cvmGet(homo, 2, 1); h[8] = cvmGet(homo, 2, 2);


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

	{

		double x = src_corners[i].x, y = src_corners[i].y;


		double Z = 1./(h[6]*x + h[7]*y + h[8]);

		double X = (h[0]*x + h[1]*y + h[2])*Z;

		double Y = (h[3]*x + h[4]*y + h[5])*Z;


		dst_corners[i] = cvPoint(cvRound(X), cvRound(Y));

	}

}

Share this post


Link to post
Share on other sites

вообщем попробовал перекомпилировать opencv2.2

(((size_t)1 << (K*(sizeof(size_t)*8-2))))
k пробовал 2,4. походу тут какое то ограничение системы.(типа больше 2-х Гб нельзя на один процесс)
IplImage* img= cvCreateImage(cvSize(30000,20000), IPL_DEPTH_8U, 3);

где то так получается максимум.(на хр, 4 гига, vs 2008, opencv2.2) около 1.8ккк байт.

Share this post


Link to post
Share on other sites

допилил внешний RANSAC, с внутренним не разобрался(там даже кол-во итераций и то фиксированное и он встроен в функцию так что там тоже допиливать\переписывать долго да еще и на С)

интересует вопрос о применении RANSAC к сопоставлению точек полученных от SURF,SIFT.

во первых что должно подаваться на вход в RANSAC просто два множества точек? должны ли количества точек в множествах совпадать?

во вторых должны ли эти точки как то быть упорядочены? (например в SURF мы сопоставляем точки по дескрипторам и получаем пары(причем связи могут быть не 1-1, а 1-N ), но потом мы эту информацию(о парах) никак не используем)

Share this post


Link to post
Share on other sites

Подкину файлик в тему :)

Язык англ. и пример кода в конце.

RANSAC_outliers_example.pdf

  • Like 1

Share this post


Link to post
Share on other sites

еще вопрос преобразование кординат через матрицу гомографии.

прямое (x,y)->(u,v)

u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);

v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);

попытался из этих соотношений вывести обратное преобразование (u,v)->(x,y)

но то ли я неправильно вывел, то ли ошибки из-за округления получаются слишком большие числа (x,y)

как оно должно выглядеть? или можно просто как то преобразовать саму матрицу(обратную посчитать) не изменяя формулы?

Share this post


Link to post
Share on other sites

еще вопрос преобразование кординат через матрицу гомографии.

прямое (x,y)->(u,v)

u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);
v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);[/code] попытался из этих соотношений вывести обратное преобразование (u,v)->(x,y) но то ли я неправильно вывел, то ли ошибки из-за округления получаются слишком большие числа (x,y) как оно должно выглядеть? или можно просто как то преобразовать саму матрицу(обратную посчитать) не изменяя формулы? MAPLE выдает такое (u->U ; v->V) : для X:
[code]x = (-V * m33 * m12 + V * m32 * m13 + m23 * m12 - m22 * m13 + m22 * U * m33 - m23 * U * m32) / (m11 * m22 - m11 * V * m32 - m12 * m21 + m12 * V * m31 - U * m31 * m22 + U * m32 * m21);
для y:
t2 = m11 * V;
t7 = U * m31;
y = -(m11 * m23 - t2 * m33 - m13 * m21 + m13 * V * m31 - t7 * m23 + U * m33 * m21) / (m11 * m22 - t2 * m32 - m12 * m21 + m12 * V * m31 - t7 * m22 + U * m32 * m21);
[/code]

  • Like 1

Share this post


Link to post
Share on other sites

У меня такой вопрос:

Есть изображение

imageat.jpg

и матрица предобразования гомографии. Что если мне необходимо трансформировать изображение не всё сразу, а сначалу одну половину, а затем другую ...

Что посоветуете? Думаю, просто смещение по X,Y будет мало?

Вот попробывал сделать нечто подобное:

uploadj.png

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×