Поиск:

Ответ в темуСоздание новой темы Создание опроса
> template matching через FFT 
:(
    Опции темы
mrgloom
Дата 25.11.2011, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



пытаюсь реализовать template matching через FFT 
формула 
position(x,y)= MAX(IFFT(FFT(Img)*FFT(template)))

возник вопрос.
размер темплейта меньше чем размер Img.
операция *, как я понял, это каждый элемент первой матрицы умножается на соответсвующий элемент второй матрицы.
значит надо дополнить матрицу template нулями, но тут непонятно куда помещать сам темплейт в верхний левый угол?
или надо вообще помещать во все возможные места и считать преобразование много раз?
потом еще вопрос с нормировкой непонятен, надо ли ее делать или нет?

http://en.wikipedia.org/wiki/Phase_correlation
вот тут формула отличается.тоже это самое что normalized cross corelation?
PM MAIL   Вверх
maxdiver
Дата 26.11.2011, 08:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 29.1.2008
Где: Саратов

Репутация: 16
Всего: 18



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

Таким образом, мы помещаем шаблон в (0;0), остальное добиваем нулями.

Теперь у нас есть два вектора, и нам надо найти скалярные произведения всех циклических сдвигов первого вектора на второй. Это решается следующим образом: к одному вектору припишем в конец его же, а другой вектор - поревёрсим (изменим порядок на противоположный) и добьём нулями до длины первого вектора, и посчитаем через FFT произведение их как многочленов. Вторая четверть получившихся коэффициентов (c n-го по 2n-1-ый - где n это размер изображения) и будет искомыми скалярными произведениями.
PM MAIL WWW ICQ   Вверх
mrgloom
Дата 28.11.2011, 08:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



Цитата

Если я правильно понял вас, то ваша задача - это поиск шаблона в изображении

 да.
 
 не очень понял, что вы написали.
 у меня не вектор, а матрица(изображение).
 результат IFFT(FFT(Img)*FFT(template)) тоже матрица и на ней надо найти максимум это и будет положением темплейта.
 я не понимаю как выполнять операцию * при различных размерах матрицы и как производить эту операцию.
 пробовал добивать темплейт нулями и почленно перемножать элементы матрицы(т.е. res(i,j)=a(i,j)*b(i,j)), но получается неправильный ответ.
 возможно надо нормировать или я что то не понимаю.
PM MAIL   Вверх
maxdiver
Дата 28.11.2011, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 29.1.2008
Где: Саратов

Репутация: 16
Всего: 18



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

Тогда, если мы сделаем сравнение двух полученных векторов, то это получится ответ, как если бы шаблон приложили в точку (0;0). Если мы сдвинем вектор шаблона на единицу, то это будет соответствовать положению шаблона (0;1), и т.д.

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

Итак, задача тривиальным образом свелась к одномерной, а здесь уже её можно решать, как я говорил выше: один вектор дополнить нулями, а другой поревёрсить и приписать к себе, и перемножить эти два вектора как многочлены, в результате часть полученных коэффициентов и будет равна искомым числам.
PM MAIL WWW ICQ   Вверх
mrgloom
Дата 28.11.2011, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



Цитата

Тогда, если мы сделаем сравнение двух полученных векторов, то это получится ответ, как если бы шаблон приложили в точку (0;0). Если мы сдвинем вектор шаблона на единицу, то это будет соответствовать положению шаблона (0;1), и т.д.


так все таки надо смотреть все возможные комбинации положения шаблона?

вот есть код, но непонятно какой операции соответсвует 
obtain the cross power spectrum
и зачем производится нормировка (возможно только лишь для того чтобы скопировать в изображение)

Код

/* obtain the FFT of img1 */
    fftw_execute( fft_img1 );
    
    /* obtain the FFT of img2 */
    fftw_execute( fft_img2 );
    
    /* obtain the cross power spectrum */
    for( i = 0; i < fft_size ; i++ ) {
        res[i][0] = ( img2[i][0] * img1[i][0] ) - ( img2[i][1] * ( -img1[i][1] ) );
        res[i][1] = ( img2[i][0] * ( -img1[i][1] ) ) + ( img2[i][1] * img1[i][0] );

        tmp = sqrt( pow( res[i][0], 2.0 ) + pow( res[i][1], 2.0 ) );

        res[i][0] /= tmp;
        res[i][1] /= tmp;
    }

    /* obtain the phase correlation array */
    fftw_execute(ifft_res);

    /* normalize and copy to result image */
    for( i = 0 ; i < fft_size ; i++ ) {
        poc_data[i] = res[i][0] / ( double )fft_size;
    }


Добавлено @ 12:45
а понял все таки в блоке /* obtain the cross power spectrum */
считается как в википедии перемножение двух комплексных чисел второе из которых комплексно сопряженное.

Это сообщение отредактировал(а) mrgloom - 28.11.2011, 12:46
PM MAIL   Вверх
mrgloom
Дата 28.11.2011, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



да и находит таким методом правильно только координаты почему то получаются
(width-maxloc.x,height-maxloc.y) , а не (maxloc.x,maxloc.y) .
+ еще смущает что 1D массивы не проссаживается ли производительность против 2D массива? (в плане считать фурье туда сюда)
PM MAIL   Вверх
maxdiver
Дата 29.11.2011, 02:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 29.1.2008
Где: Саратов

Репутация: 16
Всего: 18



Сказать честно, я не совсем понимаю, что есть DFT от матрицы. (Ведь DFT от массива имеет чёткую интерпретацию как значения многочлена с указанными коэффициентами в точках-комплексных корнях из единицы. Как это перенести на матрицы, я не понимаю.)

А решение со сведением к одномерному случаю кажется достаточно прямолинейным.

Цитата
так все таки надо смотреть все возможные комбинации положения шаблона?


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

Цитата
еще смущает что 1D массивы не проссаживается ли производительность против 2D массива? (в плане считать фурье туда сюда)


Повторюсь, я не понимаю, что такое DFT от двумерного массива. Но в моём решении фурье запускается один раз, никаких "туда-сюда" нет. И то, что мы перемножаем весь массив целиком, важно концептуально.
PM MAIL WWW ICQ   Вверх
mrgloom
Дата 15.8.2012, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



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

вообщем вопрос стоит так как по точке выдаваемой из функции корреляции получить точку смещения?

Код
class Peak
{
public:
    CvPoint pt;
    double  maxval;
};
Peak old_opencv_FFT(IplImage* src,IplImage* temp)
{
    CvSize imgSize = cvSize(src->width, src->height);
    // Allocate floating point frames used for DFT (real, imaginary, and complex) 
    IplImage* realInput = cvCreateImage( imgSize, IPL_DEPTH_64F, 1 ); 
    IplImage* imaginaryInput = cvCreateImage( imgSize, IPL_DEPTH_64F, 1 ); 
    IplImage* complexInput = cvCreateImage( imgSize, IPL_DEPTH_64F, 2 );
    int nDFTHeight= cvGetOptimalDFTSize( imgSize.height ); 
    int nDFTWidth= cvGetOptimalDFTSize( imgSize.width ); 
    CvMat* src_DFT = cvCreateMat( nDFTHeight, nDFTWidth, CV_64FC2 ); 
    CvMat* temp_DFT = cvCreateMat( nDFTHeight, nDFTWidth, CV_64FC2 );
    CvSize dftSize = cvSize(nDFTWidth, nDFTHeight);
    IplImage* imageRe = cvCreateImage( dftSize, IPL_DEPTH_64F, 1 ); 
    IplImage* imageIm = cvCreateImage( dftSize, IPL_DEPTH_64F, 1 );
    IplImage* imageImMag = cvCreateImage( dftSize, IPL_DEPTH_64F, 1 ); 
    IplImage* imageMag = cvCreateImage( dftSize, IPL_DEPTH_64F, 1 ); 

    CvMat tmp; 
    // Processing of src 
    cvScale(src,realInput,1.0,0);
    cvZero(imaginaryInput); 
    cvMerge(realInput,imaginaryInput,NULL,NULL,complexInput);
    cvGetSubRect(src_DFT,&tmp,cvRect(0,0,src->width,src->height)); 
    cvCopy(complexInput,&tmp,NULL);
    if (src_DFT->cols>src->width)
    { 
        cvGetSubRect(src_DFT,&tmp,cvRect(src->width,0,src_DFT->cols-src->width,src->height)); 
        cvZero(&tmp); 
    } 
    cvDFT(src_DFT,src_DFT,CV_DXT_FORWARD,complexInput->height); 
    cvSplit(src_DFT,imageRe,imageIm,0,0);  

    // Processing of temp
    cvScale(temp,realInput,1.0,0); 
    cvMerge(realInput,imaginaryInput,NULL,NULL,complexInput); 
    cvGetSubRect(temp_DFT,&tmp,cvRect(0,0,temp->width,temp->height)); 
    cvCopy(complexInput,&tmp,NULL); 
    if (temp_DFT->cols>temp->width) 
    { 
        cvGetSubRect(temp_DFT,&tmp,cvRect(temp->width,0,temp_DFT->cols-temp->width,temp->height)); 
        cvZero( &tmp ); 
    } 
    cvDFT(temp_DFT,temp_DFT,CV_DXT_FORWARD,complexInput->height);

    // Multiply spectrums of the scene and the model (use CV_DXT_MUL_CONJ to get correlation instead of convolution) 
    cvMulSpectrums(src_DFT,temp_DFT,src_DFT,CV_DXT_MUL_CONJ); 

    // Split Fourier in real and imaginary parts 
    cvSplit(src_DFT,imageRe,imageIm,0,0); 

    // Compute the magnitude of the spectrum components: Mag = sqrt(Re^2 + Im^2) 
    cvPow( imageRe, imageMag, 2.0 ); 
    cvPow( imageIm, imageImMag, 2.0 ); 
    cvAdd( imageMag, imageImMag, imageMag, NULL ); 
    cvPow( imageMag, imageMag, 0.5 ); 

    // Normalize correlation (Divide real and imaginary components by magnitude) 
    cvDiv(imageRe,imageMag,imageRe,1.0); 
    cvDiv(imageIm,imageMag,imageIm,1.0); 
    cvMerge(imageRe,imageIm,NULL,NULL,src_DFT); 

    // inverse dft 
    cvDFT( src_DFT, src_DFT, CV_DXT_INVERSE_SCALE, complexInput->height ); 
    cvSplit( src_DFT, imageRe, imageIm, 0, 0 ); 

    double minval = 0.0; 
    double maxval = 0.0; 
    CvPoint minloc; 
    CvPoint maxloc; 
    cvMinMaxLoc(imageRe,&minval,&maxval,&minloc,&maxloc,NULL); 

    int x=maxloc.x; // log range 
    //if (x>(imageRe->width/2)) 
    //        x = x-imageRe->width;    // positive or negative values 
    int y=maxloc.y; // angle 
    //if (y>(imageRe->height/2)) 
    //        y = y-imageRe->height; // positive or negative values 

    Peak pk;
    pk.maxval= maxval;
    pk.pt=cvPoint(x,y);
    return pk;
}
void phase_correlation2D( IplImage* src, IplImage *tpl, IplImage *poc )
{
    int     i, j, k;
    double  tmp;
    
    /* get image properties */
    int width    = src->width;
    int height   = src->height;
    int step     = src->widthStep;
    int fft_size = width * height;

    /* setup pointers to images */
    uchar   *src_data = ( uchar* ) src->imageData;
    uchar   *tpl_data = ( uchar* ) tpl->imageData;
    double  *poc_data = ( double* )poc->imageData;

    /* allocate FFTW input and output arrays */
    fftw_complex *img1 = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );
    fftw_complex *img2 = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );
    fftw_complex *res  = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );   
    
    /* setup FFTW plans */
    fftw_plan fft_img1 = fftw_plan_dft_2d( height ,width, img1, img1, FFTW_FORWARD,  FFTW_ESTIMATE );
    fftw_plan fft_img2 = fftw_plan_dft_2d( height ,width, img2, img2, FFTW_FORWARD,  FFTW_ESTIMATE );
    fftw_plan ifft_res = fftw_plan_dft_2d( height ,width, res,  res,  FFTW_BACKWARD, FFTW_ESTIMATE );
    
    /* load images' data to FFTW input */
    for( i = 0, k = 0 ; i < height ; i++ ) {
        for( j = 0 ; j < width ; j++, k++ ) {
            img1[k][0] = ( double )src_data[i * step + j];
            img1[k][1] = 0.0;
            
            img2[k][0] = ( double )tpl_data[i * step + j];
            img2[k][1] = 0.0;
        }
    }
    
    ///* Hamming window */
    //double omega = 2.0*M_PI/(fft_size-1);
    //double A= 0.54;
    //double B= 0.46;
    //for(i=0,k=0;i<height;i++)
    //{
    //    for(j=0;j<width;j++,k++)
    //    {
    //        img1[k][0]= (img1[k][0])*(A-B*cos(omega*k));
    //        img2[k][0]= (img2[k][0])*(A-B*cos(omega*k));
    //    }
    //}

    /* obtain the FFT of img1 */
    fftw_execute( fft_img1 );
    
    /* obtain the FFT of img2 */
    fftw_execute( fft_img2 );
    
    /* obtain the cross power spectrum */
    for( i = 0; i < fft_size ; i++ ) {
        res[i][0] = ( img2[i][0] * img1[i][0] ) - ( img2[i][1] * ( -img1[i][1] ) );
        res[i][1] = ( img2[i][0] * ( -img1[i][1] ) ) + ( img2[i][1] * img1[i][0] );

        tmp = sqrt( pow( res[i][0], 2.0 ) + pow( res[i][1], 2.0 ) );

        res[i][0] /= tmp;
        res[i][1] /= tmp;
    }

    /* obtain the phase correlation array */
    fftw_execute(ifft_res);

    //normalize and copy to result image
    for( i = 0 ; i < fft_size ; i++ ) {
        poc_data[i] = res[i][0] / ( double )fft_size;
    }

    /* deallocate FFTW arrays and plans */
    fftw_destroy_plan( fft_img1 );
    fftw_destroy_plan( fft_img2 );
    fftw_destroy_plan( ifft_res );
    fftw_free( img1 );
    fftw_free( img2 );
    fftw_free( res );
}

Peak FFTW_test(IplImage* src,IplImage* temp)
{
    clock_t start=clock();

    int t_w=temp->width;
    int t_h=temp->height;

    /* create a new image, to store phase correlation result */
    IplImage* poc = cvCreateImage( cvSize(temp->width,temp->height ), IPL_DEPTH_64F, 1 );

    /* get phase correlation of input images */
    phase_correlation2D( src, temp, poc );

    /* find the maximum value and its location */
    CvPoint minloc, maxloc;
    double  minval, maxval;
    cvMinMaxLoc( poc, &minval, &maxval, &minloc, &maxloc, 0 );

    /* IplImage* poc_8= cvCreateImage( cvSize(temp->width, temp->height ), 8, 1 );
    cvConvertScale(poc,poc_8,(double)255/(maxval-minval),(double)(-minval)*255/(maxval-minval));
    cvSaveImage("poc.png",poc_8); */

    cvReleaseImage( &poc );

    clock_t end=clock();

    int time= end-start;

    //fprintf( stdout, "Time= %d using clock() \n" ,time/*dt*/ );
    //fprintf( stdout, "Maxval at (%d, %d) = %2.4f\n", maxloc.x, maxloc.y, maxval );

    CvPoint pt;
    pt.x= maxloc.x;
    pt.y= maxloc.y;
    //4 случая локации точки максимальной кореляции
    //if(maxloc.x>=0&&maxloc.x<=t_w/2&&maxloc.y>=0&&maxloc.y<=t_h/2)
    //{
    //    pt.x= src->width-maxloc.x;
    //    pt.y= -maxloc.y;
    //}
    //if(maxloc.x>=t_w/2&&maxloc.x<=t_w&&maxloc.y>=0&&maxloc.y<=t_h/2)
    //{
    //    pt.x= src->width-maxloc.x;
    //    pt.y= src->height-maxloc.y;
    //}
    //if(maxloc.x>=0&&maxloc.x<=t_w/2&&maxloc.y>=t_h/2&&maxloc.y<=t_h)
    //{
    //    /*pt.x= -maxloc.x;
    //    pt.y= -maxloc.y;*/
    //    pt.x= src->width-maxloc.x; //тут непонятно
    //    pt.y= src->height-maxloc.y;
    //}    
    //if(maxloc.x>=t_w/2&&maxloc.x<=t_w&&maxloc.y>=t_h/2&&maxloc.y<=t_h)
    //{
    //    pt.x= -maxloc.x;
    //    pt.y= src->height-maxloc.y;
    //}

    Peak pk;
    pk.maxval= maxval;
    pk.pt=pt;
    return pk;
}

PM MAIL   Вверх
mrgloom
Дата 17.12.2012, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



использовал версию opencv 2.4.3 она работает на некоторых изображениях, а например на изображении где 20% перекрытия не всегда выдает не тот пик,
что то типа (w,h)-peak или -peak.
не пойму с чем это всё связано, какие то краевые проблемы или связанные с цикличностью?
когда изображения разного размера я добавляю нулями, но в зависимости от размера (см. в коде) получаются разные результаты.

вопрос можно ли дополнять нулями? есть ли разница сколько добавлять или куда помещать изображение? (я помещал в левый верхний угол, а остальное заполнял нулями).
+ еще в самом коде phaseCorrelate непонятный код по смещению.
Код
// adjust shift relative to image center...
    Point2d center((double)padded1.cols / 2.0, (double)padded1.rows / 2.0);


Код
#include "stdafx.h"

#include <opencv.hpp>

using namespace cv;
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    Mat image1= imread("1.png",0);
    Mat image2= imread("2.png",0);

    Mat r1;
    image1.convertTo(r1,CV_64F);
    Mat r2;
    image2.convertTo(r2,CV_64F);

    Point2d phaseShift1;
    Point2d phaseShift2;

    //check size
    if(r1.cols!=r2.cols||r1.rows!=r2.rows)
    {
        //image1 size 883x646
        //image2 size 882x599

        //gives peak -423 -1 (423 1)
        int n_cols= 1024;
        int n_rows= 1024;

        //gives peak  224 -1 (-224 1)
        int n_cols= max(r1.cols,r2.cols);
        int n_rows= max(r1.rows,r2.rows);

        Mat r1_pad;
        copyMakeBorder(r1,r1_pad,0,n_rows-r1.rows,0,n_cols-r1.cols, BORDER_CONSTANT, Scalar::all(0));
        Mat r2_pad;
        copyMakeBorder(r2,r2_pad,0,n_rows-r2.rows,0,n_cols-r2.cols, BORDER_CONSTANT, Scalar::all(0));

        //imwrite("b1.png",r1_pad);
        //imwrite("b2.png",r2_pad);

        //Mat hann;
        //createHanningWindow(hann, r1_pad.size(), CV_64F);
        phaseShift1 = phaseCorrelate(r1_pad, r2_pad/*, hann*/);
        phaseShift2 = phaseCorrelate(r2_pad, r1_pad/*, hann*/);
        int f=0;
    }
    else
    {
        //Mat hann;
        //createHanningWindow(hann, r1.size(), CV_64F);
        phaseShift1 = phaseCorrelate(r1, r2/*, hann*/);
        phaseShift2 = phaseCorrelate(r2, r1/*, hann*/);
    }

    return 0;
}


Код
cv::Point2d cv::phaseCorrelateRes(InputArray _src1, InputArray _src2, InputArray _window, double* response)
{
    Mat src1 = _src1.getMat();
    Mat src2 = _src2.getMat();
    Mat window = _window.getMat();

    CV_Assert( src1.type() == src2.type());
    CV_Assert( src1.type() == CV_32FC1 || src1.type() == CV_64FC1 );
    CV_Assert( src1.size == src2.size);

    if(!window.empty())
    {
        CV_Assert( src1.type() == window.type());
        CV_Assert( src1.size == window.size);
    }

    int M = getOptimalDFTSize(src1.rows);
    int N = getOptimalDFTSize(src1.cols);

    Mat padded1, padded2, paddedWin;

    if(M != src1.rows || N != src1.cols)
    {
        copyMakeBorder(src1, padded1, 0, M - src1.rows, 0, N - src1.cols, BORDER_CONSTANT, Scalar::all(0));
        copyMakeBorder(src2, padded2, 0, M - src2.rows, 0, N - src2.cols, BORDER_CONSTANT, Scalar::all(0));

        if(!window.empty())
        {
            copyMakeBorder(window, paddedWin, 0, M - window.rows, 0, N - window.cols, BORDER_CONSTANT, Scalar::all(0));
        }
    }
    else
    {
        padded1 = src1;
        padded2 = src2;
        paddedWin = window;
    }

    Mat FFT1, FFT2, P, Pm, C;

    // perform window multiplication if available
    if(!paddedWin.empty())
    {
        // apply window to both images before proceeding...
        multiply(paddedWin, padded1, padded1);
        multiply(paddedWin, padded2, padded2);
    }

    // execute phase correlation equation
    // Reference: http://en.wikipedia.org/wiki/Phase_correlation
    dft(padded1, FFT1, DFT_REAL_OUTPUT);
    dft(padded2, FFT2, DFT_REAL_OUTPUT);

    mulSpectrums(FFT1, FFT2, P, 0, true);

    magSpectrums(P, Pm);
    divSpectrums(P, Pm, C, 0, false); // FF* / |FF*| (phase correlation equation completed here...)

    idft(C, C); // gives us the nice peak shift location...

    fftShift(C); // shift the energy to the center of the frame.

    // locate the highest peak
    Point peakLoc;
    minMaxLoc(C, NULL, NULL, NULL, &peakLoc);

    // get the phase shift with sub-pixel accuracy, 5x5 window seems about right here...
    Point2d t;
    t = weightedCentroid(C, peakLoc, Size(5, 5), response);

    // max response is M*N (not exactly, might be slightly larger due to rounding errors)
    if(response)
        *response /= M*N;

    // adjust shift relative to image center...
    Point2d center((double)padded1.cols / 2.0, (double)padded1.rows / 2.0);

    return (center - t);
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.1030 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.