2010-08-09 4 views
4

Я использую преобразование Хафа в OpenCV для обнаружения линий. Тем не менее, я заранее знаю, что мне нужны линии только в очень ограниченном диапазоне углов (около 10 градусов или около того). Я делаю это в очень чувствительной к производительности настройке, поэтому я бы хотел избежать дополнительной работы, потраченной на обнаружение линий под другими углами, строки, которые я знаю заранее, мне все равно.Поиск линий с небольшим диапазоном углов в OpenCV

Я мог извлечь источник Hough из OpenCV и просто взломать его, чтобы принять параметры min_rho и max_rho, но мне нужен менее хрупкий подход (нужно вручную обновлять код с каждым обновлением OpenCV и т. Д.).

Какой лучший подход здесь?

ответ

1

Ну, я изменил функцию icvHoughlines, чтобы перейти к определенному диапазону углов. Я уверен, что есть более чистые способы, которые также играют с распределением памяти, но я получил коэффициент усиления от 100 мс до 33 мс для диапазона угла от 180 до 60 градусов, поэтому я доволен этим.

Примечание что этот код также выводит значение аккумулятора. Кроме того, я выводил только 1 строку, потому что это соответствовало моим целям, но там не было никакого выигрыша.

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

Если вы используете преобразование вероятностный Хаф, то выход в виде cvPoint каждого для линий [0] и линий [1] параметров. Мы можем получить координаты x и y для каждой из двух точек через pt1.x, pt1.y и pt2.x и pt2.y. Затем используйте простую формулу для нахождения наклона линии - (y2-y1)/(x2-x1). Взятие arctan (tan inverse) из этого даст этот угол в радианах. Затем просто отфильтруйте требуемые углы от значений для каждой полученной линии hough.

0

Я думаю, что более естественно использовать стандартную функцию HoughLines (...), которая дает набор строк непосредственно в терминах rho и theta и выбирает из него диапазон нужного угла, а не пересчитывать угол от конечных точек сегмента.