Jump to content
Compvision.ru
TroyashkA

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

Recommended Posts

Эммм, может кто-нибудь поможет? Звучит то просто - в соответствии с матрицей преобразования (9 параметров) трансформировать изображение по частям средствами OpenCV. Есть ну хотя бы какие-нибудь идеи по этому поводу? Да, я знаю, что надо смещать координаты, НО КАКИЕ и ГДЕ именно?

Надеюсь на вашу помощь!

Share this post


Link to post
Share on other sites

Эммм, может кто-нибудь поможет? Звучит то просто - в соответствии с матрицей преобразования (9 параметров) трансформировать изображение по частям средствами OpenCV. Есть ну хотя бы какие-нибудь идеи по этому поводу? Да, я знаю, что надо смещать координаты, НО КАКИЕ и ГДЕ именно?

Надеюсь на вашу помощь!

Есть одна мысль.

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

Может в чем то ошибаюсь, но похоже что это должно помочь.

post-1-0-59929100-1302265969_thumb.png

Share this post


Link to post
Share on other sites

ну так например делим изначальное изображение по X на 2 части, тогда у первого будут координаты (x,y), у второго (x+w/2,y).

Share this post


Link to post
Share on other sites

Smorodov, mrgloom спасибо! На выходных попробую НАКОНЕЦ решить эту проблему ... если что отпишусь!

Share this post


Link to post
Share on other sites

Кстати, вот результат:

post-2854-0-49827800-1303630020_thumb.pn

Пока еще кривовато, но поправимо ...

p.s. заметил, что при наложении изображений друг на друга с использованием маски (прозрачность), получаю на границе трансформированного изображения черные пиксели (причем не полностью черные ...). Как можно убрать эти пиксели на границе ? Я уже написал алгоритм, он просто проходит по границе, убирая пиксели ... но делает это не всегда хорошо, кто-нибудь поделитесь нормальным алгоритмом

Share this post


Link to post
Share on other sites

Inpaint :)

  • Like 1

Share this post


Link to post
Share on other sites

я так понимаю что эти черные линии появляются из-за накопления ошибки при повороте и надо делать интерполяцию.

п.с. код выложите.

Share this post


Link to post
Share on other sites

я так понимаю что эти черные линии появляются из-за накопления ошибки при повороте и надо делать интерполяцию.

п.с. код выложите.

TransfTest.rar

Share this post


Link to post
Share on other sites

как эти параметры высчитываются?

double traWidth = 503.15322132259524, traHeight = 554.71176535116138;

	double shiftX = 54.212963249762133, shiftY = -74.906898655217859;
вообще по идее если работаем с изображениями как с 4 углами-точками, то можно использовать
cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix);

        cvWarpPerspective( src_ext, dst, warp_matrix );

и наверно надо сделать так чтобы по 2 точки dstQuad у соседних кусков совпадали. ( хотя наверно ошибка в warp_matrix опять же накопится и даст черные полосы)

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

п.с. небольшие проекты можно прям так сюда копипастить.

Share this post


Link to post
Share on other sites

как эти параметры высчитываются?

double traWidth = 503.15322132259524, traHeight = 554.71176535116138;

	double shiftX = 54.212963249762133, shiftY = -74.906898655217859;
Они высчитываются из матрицы преобразования. Я вам где-то функцию скидывал GetCorners() вот через неё можно узнать и размеры и сдвиг.
вообще по идее если работаем с изображениями как с 4 углами-точками, то можно использовать
cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix);

        cvWarpPerspective( src_ext, dst, warp_matrix );

и наверно надо сделать так чтобы по 2 точки dstQuad у соседних кусков совпадали. ( хотя наверно ошибка в warp_matrix опять же накопится и даст черные полосы)

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

Эххх, наверное придется :( А что дает функция cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix); ? Просто матрицу преобразования на основе данных об паре четырех углов ?

п.с. небольшие проекты можно прям так сюда копипастить.

:) Окей!

Share this post


Link to post
Share on other sites

Эххх, наверное придется  А что дает функция cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix); ? Просто матрицу преобразования на основе данных об паре четырех углов ? 

да. видимо вам она бесполезна, т.к. вы отталкиваетесь от warp_matrix.

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

Share this post


Link to post
Share on other sites

Вот - добил алгоритм сегодня вечером. Результат:

При максимальной части == 40х40:

post-2854-0-18756700-1303834967_thumb.jp

При максимальной части == 100х100:

post-2854-0-81601400-1303834962_thumb.jp

При максимальной части == 543х543:

post-2854-0-94182900-1303835275_thumb.jp

p.s. Думаю, можно определять координаты следующей части при помощи направления - это должно убрать искажения, ну а потом уже применять Inpaint :)

Share this post


Link to post
Share on other sites

кстати я забыл для чего вы их делите?

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

если делите на тайлы для того чтобы находить для них точки-дескрипторы, то как потом варпаете? тайл относительно тайла? или как то усредняете матрицу преобразования по тайлам из которых состоит 1 картинка?

Share this post


Link to post
Share on other sites

кстати я забыл для чего вы их делите?

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

если делите на тайлы для того чтобы находить для них точки-дескрипторы, то как потом варпаете? тайл относительно тайла? или как то усредняете матрицу преобразования по тайлам из которых состоит 1 картинка?

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

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

Share this post


Link to post
Share on other sites

так вы варпите не через opencv? а через что?

Я исходил вот из чего: так как части взаимосвязаны, то после трансформации они также будут взаимосвязаны

ну я имел ввиду, что у разных тайлов с 1 изображения должны быть разные матрицы преобразований, хотя бы по смещению, а по повороту должны быть примерно одинаковые +-ошибка , так вот интересно какая это будет ошибка.

Share this post


Link to post
Share on other sites

так вы варпите не через opencv? а через что?

Варп через OpenCV по частям. Открытие изображения, выделение частей через GDAL (GDI+ не катит :( )

Я исходил вот из чего: так как части взаимосвязаны, то после трансформации они также будут взаимосвязаны

ну я имел ввиду, что у разных тайлов с 1 изображения должны быть разные матрицы преобразований, хотя бы по смещению, а по повороту должны быть примерно одинаковые +-ошибка , так вот интересно какая это будет ошибка.

Матрица преобразования одна. Её я вычисляю для всего изображения. В соответствии с этой матрицей трансформирую части. Как видите - неплохо выглядит, но это только с этим изображением - с другими глючит, но видимо я что-то не учел

p.s. было бы неплохо найти библиотеку, которая варпит большие изображения, скажем до 1-1,5 гигов. Если кто встречал - посоветуйте. Пробывал OpenCV, GDI+, libtiff, ну и прочие мелкие либы, даже не помню их названия - вообщем со всеми есть определенные проблемы. Вот только GDAL более-менее подходит

Share this post


Link to post
Share on other sites
Варп через OpenCV по частям. Открытие изображения, выделение частей через GDAL (GDI+ не катит )

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

или уже преобразованные тайлы каким то образом копируются через gdal в большое изображение?

какие ограничения есть в gdal? на размер изображения или на размер используемой памяти? там какой то внутренний формат?

.PSD позволяет 300к х 300к пикселей.

PSD format is limited to a maximum height and width of 30,000 pixels. .PSB (Photoshop Big) format, also known as "large document format" within Photoshop, is the extension of PSD format to images up to 300,000 pixels in width or height. That limit was apparently chosen somewhat arbitrarily by Adobe, not based on computer arithmetic constraints (it is not close to a significant power of two, as is 30,000) but for ease of software testing. PSD and PSB formats are documented.

Матрица преобразования одна. Её я вычисляю для всего изображения. В соответствии с этой матрицей трансформирую части. Как видите - неплохо выглядит, но это только с этим изображением - с другими глючит, но видимо я что-то не учел

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

Share this post


Link to post
Share on other sites

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

или уже преобразованные тайлы каким то образом копируются через gdal в большое изображение?

Второе

какие ограничения есть в gdal? на размер изображения или на размер используемой памяти? там какой то внутренний формат?

Конкретные ограничения не смотрел, но с изображением 800 мегабайт GDAL справляется

.PSD позволяет 300к х 300к пикселей.

Я использую Tiff

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

Точки и дескрипторы находятся не между тайлами, а последовательно выделяются из каждого изображения. Разбили первое изображение по частям - из каждой части выделили точки+дескрипторы, запихнули в общий массив. То же самое с другим изображением. После чего рассчитываем матрицу на основе этих двух больших массивов точек+дескрипторов. Вообщем то эта тема была создана именно поэтому, и позже превратилась в нечто большее :)

Share this post


Link to post
Share on other sites

Небольшой вопрос связанный с Surf: после того как получаем "интересные" точки типа CvSeq, как их переобразовать в матрицу вида 1хКол-во точек ?

cvExtractSURF( trainArray, 0, &trainKeypoints, &trainDescriptors, storage, params );

CvMat * temp = cvCreateMat( 1, trainDescriptors->total, CV_32FC2 );

Спасибо

Share this post


Link to post
Share on other sites

Небольшой вопрос связанный с Surf: после того как получаем "интересные" точки типа CvSeq, как их переобразовать в матрицу вида 1хКол-во точек ?

cvExtractSURF( trainArray, 0, &trainKeypoints, &trainDescriptors, storage, params );

CvMat * temp = cvCreateMat( 1, trainDescriptors->total, CV_32FC2 );

Спасибо

vector<CvPoint2D32f> points1;

CvMat * temp = cvMat(1, points1.size(), CV_32FC2, &points1[0]);

Share this post


Link to post
Share on other sites

хочу попробовать новые дескрипторы из версии 2.3

есть такой пример mser_sample.cpp в примере только выделяются области и больше ничего.

cvExtractMSER( hsv, NULL, &contours, storage, params );
соответственно, тут не точки, а контуры, получается их надо матчить через матчинг контуров? http://code.google.com/p/opencv-feature-tracker/source/browse/MSER.cxx?r=e4bfa468b10c17de22785a464d8636da83b1e35a&spec=svn9427a685b9331180e64adfe1b92916b3b571a96c'>http://code.google.com/p/opencv-feature-tracker/source/browse/MSER.cxx?r=e4bfa468b10c17de22785a464d8636da83b1e35a&spec=svn9427a685b9331180e64adfe1b92916b3b571a96c тут вообще какой то матчинг через блобы, но не понятно к какой версии относится код. такое ощущение, что в опенсв вообще матчинг не написан для mser, а это просто сайд проэкт http://code.google.com/p/opencv-feature-tracker/ а в mser.cpp написано
though the name is *contours*, the result actually is a list of point set.
Update: вроде все работает через общий интерфейс,например в matcher_simple.cpp поменять
SurfFeatureDetector detector(400);
на
CvMSERParams params = cvMSERParams();

	MserFeatureDetector detector(params);

Share this post


Link to post
Share on other sites

Вот тот проект, о котором говорил. Посмотрите, может пригодится.

И еще вопрос, вы склеиваете большие куски? Если да, то координаты найденных точек смещать надо (добавить координаты куска в общем полотне).

Объясните пожалуйста как работает этот блок и что это заметод?


CvFeatureTree* tr = cvCreateFeatureTree(desc1mat);

	    CvMat *matches = cvCreateMat(kp2->total,1,CV_32SC1);

	    CvMat *distances = cvCreateMat(kp2->total,1,CV_64FC1);

	    cvFindFeatures(tr, desc2mat, matches, distances, 1, 250);

	    cvReleaseFeatureTree(tr);



		//

	    int *reverseLookup = (int*)malloc(sizeof(int)*kp1->total);

	    //

		double *reverseLookupDist = (double*)malloc(sizeof(double)*kp1->total);

	    //

		for (int i = 0; i < kp1->total; ++i)

		{

	        reverseLookup[i] = -1;

	        reverseLookupDist[i] = DBL_MAX;

	    }


		int matchCount = 0;

	    for (int j = 0; j < kp2->total; ++j)

		{

	        int i = (int)cvGetReal2D(matches, j, 0);

	        double d = (double)cvGetReal2D(distances, j, 0);

	        if (d < reverseLookupDist[i])

			{

	            if (reverseLookupDist[i] == DBL_MAX) matchCount++;

	            reverseLookup[i] = j;

	            reverseLookupDist[i] = d;

	        }

	    }

	    points1 = cvCreateMat(1,matchCount,CV_32FC2);

	    points2 = cvCreateMat(1,matchCount,CV_32FC2);

	    CvPoint2D32f *p1, *p2;

	    int m = 0;

	    for (int j = 0; j < kp2->total; j++)

		{

	        int i = (int)cvGetReal2D(matches, j, 0);

	        if (j == reverseLookup[i])

			{

	            p1 = &((CvSURFPoint*)cvGetSeqElem(kp1,i))->pt;

	            p2 = &((CvSURFPoint*)cvGetSeqElem(kp2,j))->pt;

	            points1->data.fl[m*2] = p1->x;

	            points1->data.fl[m*2+1] = p1->y;

	            points2->data.fl[m*2] = p2->x;

	            points2->data.fl[m*2+1] = p2->y;

	            m++;

	        }

	    }

	    free(reverseLookup);

	    free(reverseLookupDist);

Share this post


Link to post
Share on other sites

Это KD-Tree, если мне не изменяет память.

Используется для быстрого поиска соседних (K-мерных) точек.

Вначале составляется вот такое дерево, на это тратится время один раз.

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

http://en.wikipedia.org/wiki/K-d_tree

Share this post


Link to post
Share on other sites

Это KD-Tree, если мне не изменяет память.

Используется для быстрого поиска соседних (K-мерных) точек.

Вначале составляется вот такое дерево, на это тратится время один раз.

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

Мне KD пришлось заменить на cvCreateFeatureTree. Просто не нашел нормального объяснения данного алгоритма на русском

Можно чуть поподробнее, если не затруднит? Такой способ как-то называется?

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.

×