Page History: Image Restoration and Reconstruction
Compare Page Revisions
Page Revision: 2010/08/06 14:50
Arithmetic mean filter
Gaussian Noise
Salt-and-Pepper Noise
Gaussian Noise & Salt-and-Pepper Noise
Code
public override Bitmap Process(Bitmap input)
{
if (input.PixelFormat != PixelFormat.Format8bppIndexed)
throw new NotSupportedException();
Bitmap output = (Bitmap)input.Clone();
int rm = M / 2;
int rn = N / 2;
int width = output.Width;
int height = output.Height;
int mn = M * N;
BitmapData inputData = input.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
BitmapData outputData = output.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
unsafe
{
byte* inputPtr = (byte*)inputData.Scan0.ToPointer();
byte* outputPtr = (byte*)outputData.Scan0.ToPointer();
for (int i = 0; i < width * height; i++)
{
int x = i % width;
int y = i / width;
if (x >= rm && y >= rn && x < width - rm && y < height - rn)
{
int sum = 0;
for (int tx = -rm; tx <= rm; tx++)
for (int ty = -rn; ty <= rn; ty++)
{
sum += inputPtr[i + tx + ty * width];
}
outputPtr[i] = (byte)(sum / mn);
}
}
}
output.UnlockBits(outputData);
input.UnlockBits(inputData);
return output;
}
Median filter
Gaussian Noise
Salt-and-Pepper Noise
Gaussian Noise & Salt-and-Pepper Noise
Code
public override Bitmap Process(Bitmap input)
{
if (input.PixelFormat != PixelFormat.Format8bppIndexed)
throw new NotSupportedException();
Bitmap output = (Bitmap)input.Clone();
int rm = M / 2;
int rn = N / 2;
int width = output.Width;
int height = output.Height;
int mn = M * N;
BitmapData inputData = input.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
BitmapData outputData = output.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
unsafe
{
byte* inputPtr = (byte*)inputData.Scan0.ToPointer();
byte* outputPtr = (byte*)outputData.Scan0.ToPointer();
for (int i = 0; i < width * height; i++)
{
int x = i % width;
int y = i / width;
if (x >= rm && y >= rn && x < width - rm && y < height - rn)
{
List<byte> sequence = new List<byte>(mn);
for (int tx = -rm; tx <= rm; tx++)
for (int ty = -rn; ty <= rn; ty++)
{
sequence.Add(inputPtr[i + tx + ty * width]);
}
sequence.Sort();
outputPtr[i] = sequence[mn / 2];
}
}
}
output.UnlockBits(outputData);
input.UnlockBits(inputData);
return output;
}
Adaptive, local noise reduction filter
Gaussian Noise
Salt-and-Pepper Noise
Gaussian Noise & Salt-and-Pepper Noise
Code
public override Bitmap Process(Bitmap input)
{
if (input.PixelFormat != PixelFormat.Format8bppIndexed)
throw new NotSupportedException();
Bitmap output = (Bitmap)input.Clone();
int rm = M / 2;
int rn = N / 2;
int width = output.Width;
int height = output.Height;
int mn = M * N;
BitmapData inputData = input.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
BitmapData outputData = output.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
unsafe
{
byte* inputPtr = (byte*)inputData.Scan0.ToPointer();
byte* outputPtr = (byte*)outputData.Scan0.ToPointer();
for (int i = 0; i < width * height; i++)
{
int x = i % width;
int y = i / width;
if (x >= rm && y >= rn && x < width - rm && y < height - rn)
{
double mL = 0; // mean
List<byte> sequence = new List<byte>(mn);
for (int tx = -rm; tx <= rm; tx++)
for (int ty = -rn; ty <= rn; ty++)
{
sequence.Add(inputPtr[i + tx + ty * width]);
mL += inputPtr[i + tx + ty * width];
}
mL /= mn;
double σL2 = 0;
foreach (byte pixel in sequence)
{
σL2 += Math.Pow(mL - pixel, 2);
}
σL2 /= mn;
double gxy = inputPtr[i];
outputPtr[i] = (byte)(gxy - Math.Min(1.0, _ση2 / σL2) * (gxy - mL));
}
}
}
output.UnlockBits(outputData);
input.UnlockBits(inputData);
return output;
}
Adaptive median filter
Gaussian Noise
Salt-and-Pepper Noise
Gaussian Noise & Salt-and-Pepper Noise
Code
public Bitmap Process(Bitmap input)
{
if (input.PixelFormat != PixelFormat.Format8bppIndexed)
throw new NotSupportedException();
Bitmap output = (Bitmap)input.Clone();
int width = output.Width;
int height = output.Height;
int scurr = 3;
int smax_local = 3;
BitmapData inputData = input.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
BitmapData outputData = output.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
unsafe
{
byte* inputPtr = (byte*)inputData.Scan0.ToPointer();
byte* outputPtr = (byte*)outputData.Scan0.ToPointer();
for (int i = 0; i < width * height; i++)
{
int x = i % width;
int y = i / width;
if (x >= 1 && y >= 1 && x < width - 1 && y < height - 1) // minimum 3x3 area
{
scurr = 3;
// if we are close to border, we cannot go beyond it
smax_local = Math.Min(x * 2 + 1, Smax);
smax_local = Math.Min(y * 2 + 1, smax_local);
smax_local = Math.Min((width - 1 - x) * 2 + 1, smax_local);
smax_local = Math.Min((height - 1 - y) * 2 + 1, smax_local);
do
{
int rm = scurr / 2;
int rn = scurr / 2;
int mn = scurr * scurr;
List<byte> sequence = new List<byte>(mn);
for (int tx = -rm; tx <= rm; tx++)
for (int ty = -rn; ty <= rn; ty++)
{
sequence.Add(inputPtr[i + tx + ty * width]);
}
sequence.Sort();
byte zmin = sequence[0];
byte zmax = sequence[mn - 1];
byte zmed = sequence[mn / 2];
byte zxy = inputPtr[i];
int A1 = zmed - zmin;
int A2 = zmed - zmax;
if (A1 > 0 && A2 < 0)
{
int B1 = zxy - zmin;
int B2 = zxy - zmax;
if (B1 > 0 && B2 < 0)
{
outputPtr[i] = zxy;
break;
}
else
{
outputPtr[i] = zmed;
break;
}
}
else
{
scurr += 2;
if (scurr > smax_local)
{
outputPtr[i] = zmed;
break;
}
}
} while (true);
}
}
}
output.UnlockBits(outputData);
input.UnlockBits(inputData);
return output;
}