Селективная область полярного преобразования OpenCV - PullRequest
1 голос
/ 30 сентября 2011

Я хочу ограничить рабочую область полярного преобразования в функции cvLogPolar в OpenCV.Я хотел бы рассмотреть возможность переписать функцию с нуля.Я разворачиваю изображение объектива «рыбий глаз», чтобы создать панораму, и хочу сделать его максимально эффективным.Большая часть изображения обрезается после преобразования, давая интересную область входного изображения в форме пончика:

fisheye lens image

Это означает, что большая часть обработки теряется на черных пикселях.

Это должно быть довольно просто, верно?Функция должна принимать два дополнительных аргумента для экстентов отсечения, radius1 и radius2.Вот соответствующая часть pol-to-cart функции cvLogPolar из imgwarp.cpp:

cvLogPolar( const CvArr* srcarr, CvArr* dstarr,
            CvPoint2D32f center, double M, int flags )
{
    cv::Ptr<CvMat> mapx, mapy;

    CvMat srcstub, *src = cvGetMat(srcarr, &srcstub);
    CvMat dststub, *dst = cvGetMat(dstarr, &dststub);
    CvSize ssize, dsize;

    if( !CV_ARE_TYPES_EQ( src, dst ))
        CV_Error( CV_StsUnmatchedFormats, "" );

    if( M <= 0 )
        CV_Error( CV_StsOutOfRange, "M should be >0" );

    ssize = cvGetMatSize(src);
    dsize = cvGetMatSize(dst);

    mapx = cvCreateMat( dsize.height, dsize.width, CV_32F );
    mapy = cvCreateMat( dsize.height, dsize.width, CV_32F );

    if( !(flags & CV_WARP_INVERSE_MAP) )
//---snip---
    else
    {
        int x, y;
        CvMat bufx, bufy, bufp, bufa;
        double ascale = ssize.height/(2*CV_PI);
        cv::AutoBuffer<float> _buf(4*dsize.width);
        float* buf = _buf;

        bufx = cvMat( 1, dsize.width, CV_32F, buf );
        bufy = cvMat( 1, dsize.width, CV_32F, buf + dsize.width );
        bufp = cvMat( 1, dsize.width, CV_32F, buf + dsize.width*2 );
        bufa = cvMat( 1, dsize.width, CV_32F, buf + dsize.width*3 );

        for( x = 0; x < dsize.width; x++ )
            bufx.data.fl[x] = (float)x - center.x;

        for( y = 0; y < dsize.height; y++ )
        {
            float* mx = (float*)(mapx->data.ptr + y*mapx->step);
            float* my = (float*)(mapy->data.ptr + y*mapy->step);

            for( x = 0; x < dsize.width; x++ )
                bufy.data.fl[x] = (float)y - center.y;

#if 1
            cvCartToPolar( &bufx, &bufy, &bufp, &bufa );

            for( x = 0; x < dsize.width; x++ )
                bufp.data.fl[x] += 1.f;

            cvLog( &bufp, &bufp );

            for( x = 0; x < dsize.width; x++ )
            {
                double rho = bufp.data.fl[x]*M;
                double phi = bufa.data.fl[x]*ascale;

                mx[x] = (float)rho;
                my[x] = (float)phi;
            }
#else
//---snip---
#endif
        }
    }
    cvRemap( src, dst, mapx, mapy, flags, cvScalarAll(0) );
}

Поскольку процедура работает путем итерации по пикселям в целевом изображении, области отсечения r1 и r2 просто потребуетсядля перевода в область строк y1 и y2.Тогда мы просто изменим цикл for: for( y = 0; y < dsize.height; y++ ) становится for( y = y1; y < y2; y++ ).Правильный?

Как насчет ограничения cvRemap?Я надеюсь, что он игнорирует неподвижные пиксели или это незначительные вычислительные затраты.

1 Ответ

2 голосов
/ 02 февраля 2012

В итоге я выполнил другую оптимизацию: я сохраняю результат операции полярного преобразования в постоянных матрицах переназначения. Это помогает МНОГО. Если вы выполняете развертывание полярности в видео с полным движением, используя одно и то же отображение полярного преобразования, вам не нужно пересчитывать преобразование с миллионами операций sin / cos в каждом кадре. Так что это просто потребовало небольшого изменения операций logPolar / linearPolar в исходном коде OpenCV, чтобы сохранить результат переназначения где-то снаружи.

...