2010-08-09 5 views
4

J'utilise la transformation Hough dans OpenCV pour détecter des lignes. Cependant, je sais d'avance que je n'ai besoin que de lignes dans une gamme d'angles très limitée (environ 10 degrés). Je le fais dans un environnement très sensible à la performance, donc je voudrais éviter le travail supplémentaire de détection des lignes à d'autres angles, des lignes que je connais d'avance, je m'en fous. Je pourrais extraire la source de Hough d'OpenCV et la hacker pour prendre les paramètres min_rho et max_rho, mais je voudrais une approche moins fragile (mettre à jour manuellement mon code avec chaque mise à jour d'OpenCV, etc.).Recherche de lignes avec une petite plage d'angles dans OpenCV

Quelle est la meilleure approche ici?

Répondre

1

Eh bien, j'ai modifié la fonction icvHoughlines pour obtenir une certaine gamme d'angles. Je suis sûr qu'il y a des manières plus propres qui jouent aussi avec l'allocation de mémoire, mais j'ai obtenu un gain de vitesse allant de 100ms à 33ms pour un angle allant de 180deg à 60deg, donc je suis content de ça.

Remarque Notez que ce code fournit également la valeur de l'accumulateur. En outre, je ne produis que 1 ligne parce que cela correspond à mes objectifs, mais il n'y avait pas de gain vraiment là.

static void 
icvHoughLinesStandard2(const CvMat* img, float rho, float theta, 
         int threshold, CvSeq *lines, int linesMax) 
{ 
    cv::AutoBuffer<int> _accum, _sort_buf; 
    cv::AutoBuffer<float> _tabSin, _tabCos; 

    const uchar* image; 
    int step, width, height; 
    int numangle, numrho; 
    int total = 0; 
    float ang; 
    int r, n; 
    int i, j; 
    float irho = 1/rho; 
    double scale; 

    CV_Assert(CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1); 

    image = img->data.ptr; 
    step = img->step; 
    width = img->cols; 
    height = img->rows; 

    numangle = cvRound(CV_PI/theta); 
    numrho = cvRound(((width + height) * 2 + 1)/rho); 

    _accum.allocate((numangle+2) * (numrho+2)); 
    _sort_buf.allocate(numangle * numrho); 
    _tabSin.allocate(numangle); 
    _tabCos.allocate(numangle); 
    int *accum = _accum, *sort_buf = _sort_buf; 
    float *tabSin = _tabSin, *tabCos = _tabCos; 

    memset(accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2)); 

    // find n and ang limits (in our case we want 60 to 120 
    float limit_min = 60.0/180.0*PI; 
    float limit_max = 120.0/180.0*PI; 

    //num_steps = (limit_max - limit_min)/theta; 
    int start_n = floor(limit_min/theta); 
    int stop_n = floor(limit_max/theta); 

    for(ang = limit_min, n = start_n; n < stop_n; ang += theta, n++) 
    { 
     tabSin[n] = (float)(sin(ang) * irho); 
     tabCos[n] = (float)(cos(ang) * irho); 
    } 



    // stage 1. fill accumulator 
    for(i = 0; i < height; i++) 
     for(j = 0; j < width; j++) 
     { 
      if(image[i * step + j] != 0) 
         // 
     for(n = start_n; n < stop_n; n++) 
       { 
        r = cvRound(j * tabCos[n] + i * tabSin[n]); 
        r += (numrho - 1)/2; 
        accum[(n+1) * (numrho+2) + r+1]++; 
       } 
     } 



    int max_accum = 0; 
    int max_ind = 0; 

    for(r = 0; r < numrho; r++) 
    { 
     for(n = start_n; n < stop_n; n++) 
     { 
      int base = (n+1) * (numrho+2) + r+1; 
      if (accum[base] > max_accum) 
      { 
       max_accum = accum[base]; 
       max_ind = base; 
      } 
     } 
    } 

    CvLinePolar2 line; 
    scale = 1./(numrho+2); 
    int idx = max_ind; 
    n = cvFloor(idx*scale) - 1; 
    r = idx - (n+1)*(numrho+2) - 1; 
    line.rho = (r - (numrho - 1)*0.5f) * rho; 
    line.angle = n * theta; 
    line.votes = accum[idx]; 
    cvSeqPush(lines, &line); 

} 
3

Si vous utilisez la Hough probabilistes transformer alors la sortie est sous la forme d'un cvPoint chacun pour les lignes [0] et les lignes de paramètres [1]. Nous pouvons obtenir x et y coordonnées pour chacun des deux points par pt1.x, pt1.y et pt2.x et pt2.y. Ensuite, utilisez la formule simple pour trouver la pente d'une ligne - (y2-y1)/(x2-x1). Prendre arctan (tan inverse) de cela donnera cet angle en radians. Il suffit ensuite de filtrer les angles souhaités à partir des valeurs pour chaque ligne de creux obtenue.

0

Je pense qu'il est plus naturel d'utiliser la fonction standart HoughLines (...), qui permet de collecter des lignes directement en termes rho et thêta et de sélectionner une plage d'angle, plutôt que de recalculer les angles.

Questions connexes