2010-07-16 101 views
8

是否有可能從霍夫變換中獲得累加器值以及rhothetaOpenCV:獲取Hough累加器值?

我問,因爲我想區分「明確定義」(即,具有較高的累加器值)和不太明確的行。

謝謝!

+1

我想知道爲什麼這個功能不是在OpenCV庫 – 2017-05-12 14:04:20

回答

13

好吧,看看cvhough.cpp文件,結構CvLinePolar只能由rho和angle定義。

這就是我們給HoughLines打電話後返回的全部內容。我正在修改C++文件,看看我能否得到選票。

更新十月二十六日:剛纔意識到這些並不是真正的答案,但更像是問題。顯然皺起了眉頭。我發現了一些關於重新編譯OpenCV的說明。我想我們必須進入代碼並對其進行修改並重新編譯。 How to install OpenCV 2.0 on win32

更新10月27日:好的,我沒有編譯我的新代碼的OpenCV的DLL,所以我最終複製粘貼我想修改到我自己的文件的特定部分。 我喜歡添加新的功能,以避免重載已定義的功能。 有4分主要的東西,你需要複製過來: 1-一些隨機定義

#define hough_cmp_gt(l1,l2) (aux[l1] > aux[l2]) 
static CV_IMPLEMENT_QSORT_EX(icvHoughSortDescent32s, int, hough_cmp_gt, const int*) 

2-重新定義行中的結構參數

typedef struct CvLinePolar2 
{ 
    float rho; 
    float angle; 
    float votes; 
} 
CvLinePolar2; 

3-被修改

的主要功能
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)); 

    for(ang = 0, n = 0; n < numangle; 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 = 0; n < numangle; n++) 
       { 
        r = cvRound(j * tabCos[n] + i * tabSin[n]); 
        r += (numrho - 1)/2; 
        accum[(n+1) * (numrho+2) + r+1]++; 
       } 
     } 

    // stage 2. find local maximums 
    for(r = 0; r < numrho; r++) 
     for(n = 0; n < numangle; n++) 
     { 
      int base = (n+1) * (numrho+2) + r+1; 
      if(accum[base] > threshold && 
       accum[base] > accum[base - 1] && accum[base] >= accum[base + 1] && 
       accum[base] > accum[base - numrho - 2] && accum[base] >= accum[base + numrho + 2]) 
       sort_buf[total++] = base; 
     } 

    // stage 3. sort the detected lines by accumulator value 
    icvHoughSortDescent32s(sort_buf, total, accum); 

    // stage 4. store the first min(total,linesMax) lines to the output buffer 
    linesMax = MIN(linesMax, total); 
    scale = 1./(numrho+2); 
    for(i = 0; i < linesMax; i++) 
    { 
     CvLinePolar2 line; 
     int idx = sort_buf[i]; 
     int n = cvFloor(idx*scale) - 1; 
     int 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); 
    } 

    cvFree((void**)&sort_buf); 
    cvFree((void**)&accum); 
    cvFree((void**)&tabSin); 
    cvFree((void**)&tabCos); 

} 

4-調用該函數的函數

CV_IMPL CvSeq* 
cvHoughLines3(CvArr* src_image, void* lineStorage, int method, 
       double rho, double theta, int threshold, 
       double param1, double param2) 
{ 
    CvSeq* result = 0; 

    CvMat stub, *img = (CvMat*)src_image; 
    CvMat* mat = 0; 
    CvSeq* lines = 0; 
    CvSeq lines_header; 
    CvSeqBlock lines_block; 
    int lineType, elemSize; 
    int linesMax = INT_MAX; 
    int iparam1, iparam2; 

    img = cvGetMat(img, &stub); 

    if(!CV_IS_MASK_ARR(img)) 
     CV_Error(CV_StsBadArg, "The source image must be 8-bit, single-channel"); 

    if(!lineStorage) 
     CV_Error(CV_StsNullPtr, "NULL destination"); 

    if(rho <= 0 || theta <= 0 || threshold <= 0) 
     CV_Error(CV_StsOutOfRange, "rho, theta and threshold must be positive"); 

    if(method != CV_HOUGH_PROBABILISTIC) 
    { 
     lineType = CV_32FC3; 
     elemSize = sizeof(float)*3; 
    } 
    else 
    { 
     lineType = CV_32SC4; 
     elemSize = sizeof(int)*4; 
    } 

    if(CV_IS_STORAGE(lineStorage)) 
    { 
     lines = cvCreateSeq(lineType, sizeof(CvSeq), elemSize, (CvMemStorage*)lineStorage); 
    } 
    else if(CV_IS_MAT(lineStorage)) 
    { 
     mat = (CvMat*)lineStorage; 

     if(!CV_IS_MAT_CONT(mat->type) || (mat->rows != 1 && mat->cols != 1)) 
      CV_Error(CV_StsBadArg, 
      "The destination matrix should be continuous and have a single row or a single column"); 

     if(CV_MAT_TYPE(mat->type) != lineType) 
      CV_Error(CV_StsBadArg, 
      "The destination matrix data type is inappropriate, see the manual"); 

     lines = cvMakeSeqHeaderForArray(lineType, sizeof(CvSeq), elemSize, mat->data.ptr, 
             mat->rows + mat->cols - 1, &lines_header, &lines_block); 
     linesMax = lines->total; 
     cvClearSeq(lines); 
    } 
    else 
     CV_Error(CV_StsBadArg, "Destination is not CvMemStorage* nor CvMat*"); 

    iparam1 = cvRound(param1); 
    iparam2 = cvRound(param2); 

    switch(method) 
    { 
    case CV_HOUGH_STANDARD: 
      icvHoughLinesStandard2(img, (float)rho, 
       (float)theta, threshold, lines, linesMax); 
      break; 

    default: 
     CV_Error(CV_StsBadArg, "Unrecognized method id"); 
    } 

    if(mat) 
    { 
     if(mat->cols > mat->rows) 
      mat->cols = lines->total; 
     else 
      mat->rows = lines->total; 
    } 
    else 
     result = lines; 

    return result; 
} 

,我想所以需要關閉所有的自動路徑設置,你可以卸載的OpenCV和使用CMake的方法自己重新編譯它,然後OpenCV的是真的不管你做到這一點。

+1

哈哈這很漂亮。我不認爲我能夠使用它,但希望有人會。 – 2010-10-29 18:59:26

2

雖然這是一個老問題,但我遇到了同樣的問題,所以我不妨提出我的解決方案。 houghlines()中的閾值爲清除投票門檻的任何點返回1。解決方案是爲每個閾值運行houghlines()(直到沒有更多投票)並將投票加在另一個數組中。在python中(也許有其他語言),當你沒有更多的投票時,它會拋出一個錯誤,所以使用try/except。

這裏是一個python的例子。我使用的數組是rho值爲-199到200,最大投票數小於100.您可以使用這些常量來滿足您的需求。您可能需要添加一行以將源圖像轉換爲灰度。

import matplotlib.pyplot as plt 

import cv2 

import math 



############ make houghspace array ############ 

houghspace = [] 

c = 0 

height = 400 

while c <= height: 

    houghspace.append([]) 

    cc = 0 

    while cc <= 180: 

     houghspace[c].append(0) 

     cc += 1 

    c+=1 



############ do transform ############ 


degree_tick = 1 #by how many degrees to check 

total_votes = 1 #votes counter 

highest_vote = 0 #highest vote in the array 



while total_votes < 100: 

    img = cv2.imread('source.pgm') 

    edges = cv2.Canny(img,50,150,apertureSize = 3) 

    lines = cv2.HoughLines(edges,1,math.pi*degree_tick/180,total_votes) 



    try: 

     for rho,theta in lines[0]: 





      a = math.cos(theta) 

      b = math.sin(theta) 

      x1 = int((a*rho) + 1000*(-b)) 

      y1 = int((b*rho) + 1000*(a)) 

      x2 = int((a*rho) - 1000*(-b)) 

      y2 = int((b*rho) - 1000*(a)) 

      cv2.line(img,(x1,y1),(x2,y2),(50,200,255),2) 

     #################add votes into the array################ 

     deradian = 180/math.pi #used to convert to degrees 

     for rho,theta in lines[0]: 

      degree = int(round(theta*deradian)) 

      rho_pos = int(rho - 200) 

      houghspace[rho_pos][degree] += 1 
    #when lines[0] has no votes, it throws an error which is caught here 

    except:  

     total_votes = 999 #exit loop 


    highest_vote = total_votes 

    total_votes += 1 
    del lines 



########### loop finished ############################### 
print highest_vote 



############################################################# 

################### plot the houghspace ################### 


maxy = 200 #used to offset the y-axis 

miny = -200 #used to offset the y-axis 

#the main graph 

fig = plt.figure(figsize=(10, 5)) 

ax = fig.add_subplot(111) 

ax.set_title('Houghspace') 

plt.imshow(houghspace, cmap='gist_stern') 

ax.set_aspect('equal') 

plt.yticks([0,-miny,maxy-miny], [miny,0,maxy]) 

#the legend 
cax = fig.add_axes([0, 0.1, 0.78, 0.8]) 

cax.get_xaxis().set_visible(False) 

cax.get_yaxis().set_visible(False) 

cax.patch.set_alpha(0) 

cax.set_frame_on(False) 

plt.colorbar(orientation='vertical') 

#plot 

plt.show() 
+1

我不會投這個解決方案,因爲它會產生很大的計算開銷。此外,退出循環與例外是不好的做法 - 例外是非常昂貴的,他們是爲其他目的而發明的 – 2017-05-12 14:11:14