How To Make Gamma Noise On Images – C# Guide
Gamma noise is one of the noise models we use to simulate practical data corruption. This guide shows how to apply it on images.
Filter by Category
Gamma noise is one of the noise models we can simulate on data. In our particular case, we are going to add noise to an image. Therefore, we will need to use a probability distribution function that makes that noise data.
Most commonly, the reasons for noise in images are low quality equipment and impact of environment conditions. However corruption doesn’t only happen when we’re acquiring the image, it also happens while transmitting it.
Gamma noise or Erlang noise is very similiar to Rayleigh noise regarding the shape of distribution curve. In essence, it begins with a steep slope and ends smoothly, much like Gaussian does. We can see what we just described in the following graph.
Let’s clear up a few things first before we move on to the formulation of the probability distribution function of the graph shown above.
Firstly, z axis represents the intensity values along which we distribute the noise pixel values. Secondly, a and b parameters are for shaping the curve. Now that we know what’s what, we can take a look at the function.
The ! below the fraction indicates the factorial of the number in the brackets and e is the Eulers constant.
I’ve written a function that makes noise with probability distribution function. I’ll break it down how it works.
Firstly, it calculates probabilities across all intensities and stores them into array. Secondly, we take those values and create an image histogram. And lastly we take all those distributed pixel values, store them into array and scramble it.
public static Bitmap GammaNoise(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[] erlang = new double[256];
double a = 2;
double b = 10;
Random rnd = new Random();
double sum = 0;
for (int i = 0; i < 256; i++)
{
double step = (double)i * 0.1;
if (step >= 0)
{
erlang[i] = (double)(Math.Exp(-a * step) * (Math.Pow(a, b) * Math.Pow(step, b - 1)) / NoiseDemo.Factorial((int)b - 1));
}
else
{
erlang[i] = 0;
}
sum += erlang[i];
}
for (int i = 0; i < 256; i++)
{
erlang[i] /= sum;
erlang[i] *= bytes;
erlang[i] = (int)Math.Floor(erlang[i]);
}
int count = 0;
for (int i = 0; i < 256; i++)
{
for (int j = 0; j < (int)erlang[i]; j++)
{
noise[j + count] = (byte)i;
}
count += (int)erlang[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;
}
The reason we make noise artificially is to find best restoration and reconstruction techniques on all types of data. You’re able to download the project and examine the code yourself.