OpenCV:得到Hough累加器值?

时间:2010-07-16 14:40:37

标签: opencv

是否可以从Hough变换中获取累加器值以及rhotheta

我问,因为我想区分“定义良好”的行(即具有高累加器值的行)和行列不明确的行。

谢谢!

2 个答案:

答案 0 :(得分:14)

好的,所以查看cvhough.cpp文件,结构CvLinePolar仅由rho和angle定义。

这是因为我们调用HoughLines而传回的所有内容。我正在修改c ++文件,看看我是否可以获得投票。

更新oct 26:刚刚意识到这些不是真正的答案,而是更像问题。显然不满意。我找到了一些关于重新编译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 :(得分: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()