1

画像にポイントがあります。最も共線的な点を検出する必要があります。一番速い方法はハフ変換を使うことですが、opencv の方法を変更する必要があります。実際には、検出された線で半共線の点が返される必要があります。このため、極線構造を変更しました。画像に示すように、ほぼ検出されたポイントを検出するには、許容しきい値も必要です。誰かがこのしきい値を調整する方法を手伝ってくれますか? それらが属する線を検出するには、少なくとも 4 つの半共線ポイントが必要です。 例1 例 2 例 3

  1. 最初の画像のポイントは、6 つの重なった線によって検出されました

  2. 中間画像の点は何も検出されませんでした

  3. 3 番目の点は 3 本の線で検出されました

`![ここに画像の説明を入力してください ここに画像の説明を入力 ここに画像の説明を入力

重複した先取特権を取り除く最善の方法はどれですか?? または、許容範囲のしきい値を調整して、セミコリニア ポイントを 1 行だけ検出するにはどうすればよいですか?

これは私自身の関数呼び出しです:

vector<CvLinePolar2> lines;
CvMat c_image = source1; // loaded image
HoughLinesStandard(&c_image,1,CV_PI/180,4,&lines,INT_MAX);

    typedef struct CvLinePolar2
    {
      float rho;
      float angle;
      vector<CvPoint> points;
    };

void HoughLinesStandard( const CvMat* img, float rho, float theta,
                   int threshold, vector<CvLinePolar2> *lines, int linesMax= INT_MAX )
{
cv::AutoBuffer<int> _accum, _sort_buf;
cv::AutoBuffer<float> _tabSin, _tabCos;


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

vector<vector<CvPoint>> lpoints;
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) );
//memset( lpoints, 0, sizeof(lpoints) );
lpoints.resize(sizeof(accum[0]) * (numangle+2) * (numrho+2));
float ang = 0;
for(int 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 )
        {
            CvPoint pt;
            pt.x = j; pt.y = i;
            for(int n = 0; n < numangle; n++ )
            {
                int r = cvRound( j * tabCos[n] + i * tabSin[n] );
                r += (numrho - 1) / 2;

                int ind = (n+1) * (numrho+2) + r+1;
                int s = accum[ind];
                accum[ind]++;

                lpoints[ind].push_back(pt);


            }

        }
    }

// stage 2. find local maximums
for(int r = 0; r < numrho; r++ )
    for(int 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.points = lpoints[idx];

    lines->push_back(line);
}

}

4

2 に答える 2

0

1 つのアプローチは、潜在的な行の候補セットを間引く非最大抑制です。細線化された可能性のある線を特定したら、角度または空間の違いのしきい値を満たす残りの線の平均を計算できます。

于 2013-05-01T21:11:39.043 に答える