2011-09-30 6 views
1

Je souhaite limiter la zone de fonctionnement de la transformée polaire dans la fonction cvLogPolar d'OpenCV. Je envisagerais de réécrire la fonction à partir de zéro. Je déballe une image de lentille fisheye pour donner un panorama, et je veux la rendre aussi efficace que possible. Une grande partie de l'image est coupée à une distance après la transformation, ce qui donne une région en forme d'anneau d'intérêt dans l'image d'entrée:Région sélective de la transformation polaire OpenCV

fisheye lens image

Cela signifie que beaucoup de traitement est gaspillé sur des pixels noirs.

Cela devrait être assez simple, non? La fonction doit prendre deux arguments supplémentaires pour les extensions d'écrêtage, radius1 et radius2. Voici la partie pol à panier pertinente de la fonction cvLogPolar de 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)); 
} 

Depuis les travaux de routine par itérer pixels dans l'image de destination, la zone de découpage r1 et r2 aurait juste besoin d'être traduit en y1 et y2 région de ligne. Ensuite, nous changeons simplement la boucle for: for(y = 0; y < dsize.height; y++) devient for(y = y1; y < y2; y++). Correct?

Qu'en est-il de la contrainte cvRemap? J'espère qu'il ignore les pixels non importés ou que c'est un coût de calcul négligeable.

Répondre

2

J'ai fini par faire une optimisation différente: je stocke le résultat de l'opération de transformation polaire dans les matrices de remappage persistantes. Cela aide beaucoup. Si vous effectuez un défilement polaire sur une vidéo en mouvement intégral en utilisant la même correspondance de transformation polaire à tout moment, vous ne voulez pas recalculer la transformation avec un million d'opérations sin/cos chaque image. Cela a donc nécessité quelques petites modifications sur les opérations logPolar/linearPolar dans la source OpenCV pour enregistrer le résultat de la réaffectation quelque part à l'extérieur.

+0

C'est un vieux post mais je suis vraiment (vraiment) intéressé par vos résultats! Pourriez-vous expliquer vos modifications sur les opérations lopPolar/linearPolar ou ... hum ... poster du code? Merci beaucoup ! –

+0

En fait j'essaye de faire l'inverse: coordonnées cartésiennes à polaires, mais je n'arrive pas à utiliser la fonction cartToPolar ... –

Questions connexes