如何在图像中添加高斯噪声?
0 877
0

最好使用C++(🙏)

收藏
2021-04-01 17:12 更新 正直的烤面包 •  3132
共 1 个回答
高赞 时间
0

当我们收集有关某个事件或自然事件的大量数据时,我们经常可以看到高斯分布的模式。我们也称其为正态分布,我们将使用它来计算高斯噪声的随机值。

以下公式是我们的高斯概率分布函数。

如果我们看一下公式,则有3个未知变量,分别是σ(sigma),y和μ(mi)。 Sigma和mi代表标准偏差和均值,它们会影响分布值的位置和宽度。

从公式中可以看出,我们对2的乘方使用标准偏差,这是分布的方差。我们尚未解释的唯一未知数是y,它是我们的随机变量。因此,我们需要使用随机数生成器类来生成此数字。

我感到我们还应该提到,分布曲线中所有计算值的总和等于1。因此,我们还需要将这些值带到可显示的范围,以消除图像噪声。

我们可以使用之前在频域中的拉普拉斯滤波器的教程中使用过的特征缩放公式来实现。

生成高斯噪声后,我们需要将其应用于图像。我们可以通过将图像像素值与生成的噪声值相加来做到这一点。

原始图像作为输入,并添加噪声,然后输出最终结果。

public static Bitmap GaussianNoise(this Bitmap image)
     {
         int w = image.Width;
         int h = image.Height;

         BitmapData image_data = image.LockBits(
             new Rectangle(0, 0, w, h),
             ImageLockMode.ReadOnly,
             PixelFormat.Format24bppRgb);
         int bytes = image_data.Stride * image_data.Height;
         byte[] buffer = new byte[bytes];
         byte[] result = new byte[bytes];
         Marshal.Copy(image_data.Scan0, buffer, 0, bytes);
         image.UnlockBits(image_data);

         byte[] noise = new byte[bytes];
         double[] gaussian = new double[256];
         int std = 20;
         Random rnd = new Random();
         double sum = 0;
         for (int i = 0; i < 256; i++)
         {
             gaussian[i] = (double)((1 / (Math.Sqrt(2 * Math.PI) * std)) * Math.Exp(-Math.Pow(i, 2) / (2 * Math.Pow(std, 2))));
             sum += gaussian[i];
         }

         for (int i = 0; i < 256; i++)
         {
             gaussian[i] /= sum;
             gaussian[i] *= bytes;
             gaussian[i] = (int)Math.Floor(gaussian[i]);
         }

         int count = 0;
         for (int i = 0; i < 256; i++)
         {
             for (int j = 0; j < (int)gaussian[i]; j++)
             {
                 noise[j + count] = (byte)i;
             }
             count += (int)gaussian[i];
         }

         for (int i = 0; i < bytes - count; i++)
         {
             noise[count + i] = 0;
         }

         noise = noise.OrderBy(x => rnd.Next()).ToArray();

         for (int i = 0; i < bytes; i++)
         {
             result[i] = (byte)(buffer[i] + noise[i]);
         }

         Bitmap result_image = new Bitmap(w, h);
         BitmapData result_data = result_image.LockBits(
             new Rectangle(0, 0, w, h),
             ImageLockMode.WriteOnly,
             PixelFormat.Format24bppRgb);
         Marshal.Copy(result, 0, result_data.Scan0, bytes);
         result_image.UnlockBits(result_data);
         return result_image;
     }

         int count = 0;         for (int i = 0; i < 256; i++)         {             for (int j = 0; j < (int)gaussian[i]; j++)             {                 noise[j + count] = (byte)i;             }             count += (int)gaussian[i];         }         for (int i = 0; i < 256; i++)         {             for (int j = 0; j < (int)gaussian[i]; j++)             {                 noise[j + count] = (byte)i;             }             count += (int)gaussian[i];         }

收藏
2021-04-02 08:40 更新 阿托 •  12609