Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 对于sigma=20,哪种是简单高斯模糊或高斯模糊的FFT最好?_Algorithm_Gpu - Fatal编程技术网

Algorithm 对于sigma=20,哪种是简单高斯模糊或高斯模糊的FFT最好?

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

我正在做一个程序来模糊CUDA中的16位灰度图像

在我的程序中,如果我使用sigma=20或30的高斯模糊函数,它会花费很多时间,而sigma=2.0或3.0时速度很快

我在一些网站上读到,Guaussian模糊与FFT对于大内核大小或大sigma值是很好的:

  • 这是真的吗
  • 我应该使用哪种算法:简单高斯模糊还是带FFT的高斯模糊
我的Guassian Blur代码如下。在我的代码中,是否有错误

在这里输入代码

__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(一个数量级)。