pea*_*man 12 opencv image-processing edge-detection
我试图实现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;
Run Code Online (Sandbox Code Playgroud)
但是,我觉得这可以更有效地完成.是否可以通过较少的数据传递来完成?
这里的问题让我了解了可分离的过滤器,但是我太过于理解如何在这种情况下应用它们的图像处理新手.
谁能给我一些关于如何优化这一点的指示?
Abh*_*kur 11
可分离滤波器的工作方式与普通高斯滤波器相同.当图像尺寸较大时,可分离滤波器比普通高斯滤波器快.可以分析地形成滤波器核,并且可以将滤波器分成两个1维矢量,一个水平矢量和一个垂直矢量.
例如..
考虑过滤器
1 2 1
2 4 2
1 2 1
Run Code Online (Sandbox Code Playgroud)
该滤波器可以分为水平矢量(H)1 2 1和垂直矢量(V)1 2 1.现在这些两组滤波器应用于图像.矢量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();
}
Run Code Online (Sandbox Code Playgroud)
另一种改进高斯模糊计算的方法是使用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;
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.:)
小智 5
我知道这个帖子很旧。但这个问题很有趣,可能会引起未来的读者的兴趣。据我所知,DoG 过滤器是不可分离的。所以剩下两个解决方案:1)通过两次调用函数 GaussianBlur() 计算两个卷积,然后减去两个图像 2)通过计算两个高斯内核的差异来制作内核,然后将其与图像卷积。
关于哪个解决方案更快:解决方案 2 乍一看似乎更快,因为它只对图像进行一次卷积。但这不涉及可分离的过滤器。相反,第一种解决方案涉及两个可分离的过滤器,并且最终可能会更快。(我不知道 OpenCV 函数 GaussianBlur() 是如何优化的,以及它是否使用可分离滤波器。但很有可能。)
但是,如果使用 FFT 技术进行卷积,则第二种解决方案肯定会更快。如果有人有任何建议要添加或希望纠正我,请这样做。