13

エッジ検出の特定のケースのために、guassiansの違い(DoG )を実装しようとしています。アルゴリズムの名前が示すように、実際にはかなり簡単です。

Mat g1, g2, result;
Mat img = imread("test.png", CV_LOAD_IMAGE_COLOR); 
GaussianBlur(img, g1, Size(1,1), 0);
GaussianBlur(img, g2, Size(3,3), 0);
result = g1 - g2;

しかし、これはもっと効率的にできると思います。おそらく、データをより少ないパスで実行できますか?

ここでの質問は、分離可能なフィルターについて私に教えてくれましたが、私は画像処理の初心者であり、この場合にそれらを適用する方法を理解することはできません。

誰かがこれを最適化する方法についていくつかの指針を教えてもらえますか?

4

2 に答える 2

11

分離可能なフィルターは、通常のガウスフィルターと同じように機能します。画像サイズが大きい場合、分離可能なフィルターは通常のガウス分布よりも高速です。フィルタカーネルは分析的に形成でき、フィルタは2つの1次元ベクトル(1つは水平、もう1つは垂直)に分離できます。

例えば..

フィルタを次のように考えます

1 2 1
2 4 2
1 2 1

このフィルターは、水平ベクトル(H)1 2 1と垂直ベクトル(V)1 2 1に分けることができます。これで、これら2つのフィルターのセットが画像に適用されます。ベクトルHは水平方向のピクセルに適用され、Vは垂直方向のピクセルに適用されます。次に、結果を合計してガウスぼかしを取得します。分離可能なガウスぼかしを行う関数を提供しています。(コメントについて私に聞かないでください、私はあまりにも怠惰です:P)

Mat sepConv(Mat input, int radius)
{


Mat sep;
Mat dst,dst2;

int ksize = 2 *radius +1;
double sigma = radius / 2.575;

Mat gau = getGaussianKernel(ksize, sigma,CV_32FC1);

Mat newgau = Mat(gau.rows,1,gau.type());
gau.col(0).copyTo(newgau.col(0));


filter2D(input, dst2, -1, newgau);


filter2D(dst2.t(), dst, -1, newgau);


return dst.t();


}

ガウスぼかしの計算を改善するもう1つの方法は、FFTを使用することです。データサイズがかなり大きい場合、FFTベースの畳み込みは分離可能なカーネル法よりもはるかに高速です。

クイックグーグル検索は私に次の機能を提供しました

Mat Conv2ByFFT(Mat A,Mat B)
{
Mat C;
// reallocate the output array if needed
C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type());
Size dftSize;
// compute the size of DFT transform
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);

// allocate temporary buffers and initialize them with 0's
Mat tempA(dftSize, A.type(), Scalar::all(0));
Mat tempB(dftSize, B.type(), Scalar::all(0));

// copy A and B to the top-left corners of tempA and tempB, respectively
Mat roiA(tempA, Rect(0,0,A.cols,A.rows));
A.copyTo(roiA);
Mat roiB(tempB, Rect(0,0,B.cols,B.rows));
B.copyTo(roiB);

// now transform the padded A & B in-place;
// use "nonzeroRows" hint for faster processing
Mat Ax = computeDFT(tempA);
Mat Bx = computeDFT(tempB);

// multiply the spectrums;
// the function handles packed spectrum representations well
mulSpectrums(Ax, Bx, Ax,0,true);

// transform the product back from the frequency domain.
// Even though all the result rows will be non-zero,
// we need only the first C.rows of them, and thus we
// pass nonzeroRows == C.rows
//dft(Ax, Ax, DFT_INVERSE + DFT_SCALE, C.rows);

updateMag(Ax);
Mat Cx = updateResult(Ax);

//idft(tempA, tempA, DFT_SCALE, A.rows + B.rows - 1 );
// now copy the result back to C.
Cx(Rect(0, 0, C.cols, C.rows)).copyTo(C);
//C.convertTo(C, CV_8UC1);
// all the temporary buffers will be deallocated automatically
return C;

}

お役に立てれば。:)

于 2013-01-07T10:34:17.903 に答える
5

私はこの投稿が古いことを知っています。しかし、問題は興味深いものであり、将来の読者を不安にさせる可能性があります。私の知る限り、DoGフィルターは分離できません。したがって、2つの解決策が残っています。1)関数GaussianBlur()を2回呼び出して両方の畳み込みを計算し、次に2つの画像を減算します。2)2つのガウスカーネルの差を計算してカーネルを作成し、それを画像と畳み込みます。

どのソリューションが高速かについて:ソリューション2は、画像を1回だけ畳み込むため、一見すると高速に見えます。ただし、これには分離可能なフィルターは含まれません。それどころか、最初の解決策は2つの分離可能なフィルターを含み、最終的にはより高速になる可能性があります。(OpenCV関数GaussianBlur()がどのように最適化されているか、分離可能なフィルターを使用しているかどうかはわかりません。しかし、可能性があります。)

ただし、FFT手法を使用して畳み込みを行う場合は、2番目のソリューションの方が確実に高速です。誰かが私を追加するためのアドバイスがあるか、私を修正したい場合は、してください。

于 2016-10-10T13:37:35.937 に答える