Algorithm 对于sigma=20,哪种是简单高斯模糊或高斯模糊的FFT最好?
我正在做一个程序来模糊CUDA中的16位灰度图像 在我的程序中,如果我使用sigma=20或30的高斯模糊函数,它会花费很多时间,而sigma=2.0或3.0时速度很快 我在一些网站上读到,Guaussian模糊与FFT对于大内核大小或大sigma值是很好的:Algorithm 对于sigma=20,哪种是简单高斯模糊或高斯模糊的FFT最好?,algorithm,gpu,Algorithm,Gpu,我正在做一个程序来模糊CUDA中的16位灰度图像 在我的程序中,如果我使用sigma=20或30的高斯模糊函数,它会花费很多时间,而sigma=2.0或3.0时速度很快 我在一些网站上读到,Guaussian模糊与FFT对于大内核大小或大sigma值是很好的: 这是真的吗 我应该使用哪种算法:简单高斯模糊还是带FFT的高斯模糊 我的Guassian Blur代码如下。在我的代码中,是否有错误 在这里输入代码 __global__ void gaussian_blur( unsign
- 这是真的吗李>
- 我应该使用哪种算法:简单高斯模糊还是带FFT的高斯模糊李>
__global__
void gaussian_blur(
unsigned short* const blurredChannel, // return value: blurred channel (either red, green, or blue)
const unsigned short* const inputChannel, // red, green, or blue channel from the original image
int rows,
int cols,
const float* const filterWeight, // gaussian filter weights. The weights look like a bell shape.
int filterWidth // number of pixels in x and y directions for calculating average blurring
)
{
int r = blockIdx.y * blockDim.y + threadIdx.y; // current row
int c = blockIdx.x * blockDim.x + threadIdx.x; // current column
if ((r >= rows) || (c >= cols))
{
return;
}
int half = filterWidth / 2;
float blur = 0.f; // will contained blurred value
int width = cols - 1;
int height = rows - 1;
for (int i = -half; i <= half; ++i) // rows
{
for (int j = -half; j <= half; ++j) // columns
{
// Clamp filter to the image border
int h = min(max(r + i, 0), height);
int w = min(max(c + j, 0), width);
// Blur is a product of current pixel value and weight of that pixel.
// Remember that sum of all weights equals to 1, so we are averaging sum of all pixels by their weight.
int idx = w + cols * h; // current pixel index
float pixel = static_cast<float>(inputChannel[idx]);
idx = (i + half) * filterWidth + j + half;
float weight = filterWeight[idx];
blur += pixel * weight;
}
}
blurredChannel[c + r * cols] = static_cast<unsigned short>(blur);
}
void createFilter(float *gKernel,double sigma,int radius)
{
double r, s = 2.0 * sigma * sigma;
// sum is for normalization
double sum = 0.0;
// generate 9*9 kernel
int m=0;
for (int x = -radius; x <= radius; x++)
{
for(int y = -radius; y <= radius; y++)
{
r = std::sqrtf(x*x + y*y);
gKernel[m] = (exp(-(r*r)/s))/(3.14 * s);
sum += gKernel[m];
m++;
}
}
m=0;
// normalize the Kernel
for(int i = 0; i < (radius*2 +1); ++i)
for(int j = 0; j < (radius*2 +1); ++j)
gKernel[m++] /= sum;
}
int main()
{
cudaError_t cudaStatus;
const int size =81;
float gKernel[size];
float *dev_p=0;
cudaStatus = cudaMalloc((void**)&dev_p, size * sizeof(float));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
}
createFilter(gKernel,20.0,4);
cudaStatus = cudaMemcpy(dev_p, gKernel, size* sizeof(float), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMemcpy failed!");
}
/* i read image Buffere in unsigned short that code is not added here ,becouse it is large , and copy image data of buffere from host to device*/
/* So, suppose i have unsigned short *d_img which contain image data */
cudaMalloc( (void**)&d_img, length* sizeof(unsigned short));
cudaMalloc( (void**)&d_blur_img, length* sizeof(unsigned short));
static const int BLOCK_WIDTH = 32;
int image_width=1580.0,image_height=1050.0;
int x = static_cast<int>(ceilf(static_cast<float>(image_width) / BLOCK_WIDTH));
int y = static_cast<int>(ceilf(static_cast<float>((image_height) ) / BLOCK_WIDTH));
const dim3 grid (x, y, 1); // number of blocks
const dim3 block(BLOCK_WIDTH, BLOCK_WIDTH, 1);
gaussian_blur<<<grid,block>>>(d_blur_img,d_img,1050.0,1580.0,dev_p,9.0);
cudaDeviceSynchronize();
/* after bluring image i will copied buffer from Device to Host and free gpu memory */
cudaFree(d_img);
cudaFree(d_blur_img);
cudaFree(dev_p);
return 0;
}
\uuuu全局\uuuu
空洞高斯模糊(
无符号short*const blurredChannel,//返回值:模糊通道(红色、绿色或蓝色)
const unsigned short*const inputChannel,//原始图像中的红色、绿色或蓝色通道
int行,
int cols,
常量浮点*常量过滤器权重,//高斯过滤器权重。权重看起来像钟形。
int filterWidth//x和y方向上用于计算平均模糊的像素数
)
{
int r=blockIdx.y*blockDim.y+threadIdx.y;//当前行
int c=blockIdx.x*blockDim.x+threadIdx.x;//当前列
if((r>=行)| |(c>=列))
{
返回;
}
int half=过滤器宽度/2;
float blur=0.f;//将包含模糊值
int width=cols-1;
整数高度=行数-1;
对于(int i=-half;i简短回答:这两种算法在图像模糊方面都很好,因此请随意为您的用例选择最佳(最快)的算法
内核大小和sigma值是直接相关的:sigma越大,内核越大(因此每个像素的操作越多,以获得最终结果)。
如果您实现了一个简单的卷积,那么您应该尝试一个可分离的卷积实现;它将减少一个数量级的计算时间
现在有了更多的见解:它们实现了几乎相同的高斯模糊操作。为什么几乎如此?这是因为对图像进行FFT时会隐式地对其进行周期性处理。因此,在图像的边界处,卷积核会看到一个图像已缠绕在其边缘上。这称为循环卷积(因为包装)另一方面,高斯模糊实现了一个简单的线性卷积我将添加我的内核代码,并使用该kerenal模糊一个16位灰度图像。它是否正确?sigma的kerenel大小将是30?在我的代码中,内核的固定大小是9*9,但sigma=20 o的内核大小是多少r 30(表示大西格玛值)?高斯核需要足够大,以包含最重要的模糊系数。请参阅典型的方法。通常情况下,当sigma=20或30或更多时,guassian kerenal的大小是多少?经验法则:高斯系数在+/-3*sigma处消失。sigma=20意味着3*sigma=60,因此核宽度应在120左右像素)。接近通过反转OpenCV的公式(给出141像素)可以找到的值不是真正的高斯模糊,但如果你不需要它是完美的,那么这可能对你有用:而且,对于较大的图像,分区fft卷积通常更快kernels@Pete一般来说,对于sigma=20或30或mor,guassian kerenal的大小是多少?@Pete,因为如果我将内核大小设为41*41或更大,那么我的代码需要花费超过1秒的时间我想完成高斯模糊中的模糊方法是一个可分离的滤波器。通过使用两个过程(垂直+水平),您可以将算法的复杂度从N^2降低到N(一个数量级)。