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

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

Recommended Posts

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Inpaint :)

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

TransfTest.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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 точки например) точек на стыке и делать хотя бы линейную интерполяцию, т.е. усреднять.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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); ? Просто матрицу преобразования на основе данных об паре четырех углов ?

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

:) Окей!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

При максимальной части == 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 :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Варп через 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 тайлов и между парами тайлов находятся точки-декрипторы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Второе

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

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

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

Я использую Tiff

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

Спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Небольшой вопрос связанный с 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]);

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

хочу попробовать новые дескрипторы из версии 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);

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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


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);

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×