空间域中的锐化滤波器
Sharpen Filter in the spatial domain
以下例程仅锐化 8 位索引灰度。
public static Bitmap Sharpen(Bitmap image, double strength)
{
using (var bitmap1 = image as Bitmap)
{
if (bitmap1 != null)
{
var bitmap = bitmap1.Clone() as Bitmap;
int width = image.Width;
int height = image.Height;
// Create sharpening filter.
const int filterSize = 5;
var filter = new double[,]
{
{-1, -1, -1, -1, -1},
{-1, 2, 2, 2, -1},
{-1, 2, 16, 2, -1},
{-1, 2, 2, 2, -1},
{-1, -1, -1, -1, -1}
};
int channels = sizeof(byte);
double bias = 1.0 - strength;
double factor = strength / 16.0;
const int halfOfFilerSize = filterSize / 2;
byte[,] result = new byte[image.Width, image.Height];
// Lock image bits for read/write.
if (bitmap != null)
{
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite,
PixelFormat.Format8bppIndexed);
// Declare an array to hold the bytes of the bitmap.
int memorySize = bitmapData.Stride * height;
byte[] memory = new byte[memorySize];
// Copy the RGB values into the local array.
Marshal.Copy(bitmapData.Scan0, memory, 0, memorySize);
int rgb;
// Fill the color array with the new sharpened color values.
for (int y = halfOfFilerSize; y < height - halfOfFilerSize; y++)
{
for (int x = halfOfFilerSize; x < width - halfOfFilerSize; x++)
{
for (int filterY = 0; filterY < filterSize; filterY++)
{
double grayShade = 0.0;
for (int filterX = 0; filterX < filterSize; filterX++)
{
int imageX = (x - halfOfFilerSize + filterX + width) % width;
int imageY = (y - halfOfFilerSize + filterY + height) % height;
rgb = imageX * bitmapData.Stride + channels * imageY;
grayShade += memory[rgb + 0] * filter[filterX, filterY];
}
rgb = x * bitmapData.Stride + channels * y;
int b = Math.Min(Math.Max((int)(factor * grayShade + (bias * memory[rgb + 0])), 0), 255);
result[x, y] = (byte)b;
}
}
}
// Update the image with the sharpened pixels.
for (int x = halfOfFilerSize; x < width - halfOfFilerSize; x++)
{
for (int y = halfOfFilerSize; y < height - halfOfFilerSize; y++)
{
rgb = y * bitmapData.Stride + 3 * x;
memory[rgb + 0] = result[x, y];
}
}
// Copy the RGB values back to the bitmap.
Marshal.Copy(memory, 0, bitmapData.Scan0, memorySize);
// Release image bits.
bitmap.UnlockBits(bitmapData);
}
return bitmap;
}
}
return null;
}
此例程在以下行中抛出异常:
grayShade += memory[rgb + 0] * filter[filterX, filterY];
我哪里算错了?
.
.
P.S. 界面代码:
private void sharpenButton_Click(object sender, EventArgs e)
{
Bitmap sharpened = ImageSharpener.Sharpen(_inputImage, 0.5);
sharpenedPictureBox.Image = sharpened;
}
这个:
rgb = imageX * bitmapData.Stride + channels * imageY;
应该是:
rgb = imageY * bitmapData.Stride + channels * imageX;
还有这个:
rgb = x * bitmapData.Stride + channels * y;
应该是:
rgb = y * bitmapData.Stride + channels * x;
另外,你不应该乘以 channels
,那已经是 bitmapData.Stride
的一部分了。另外,请注意 channels = sizeof(byte)
,它只是 1,而不是 3(由 rgb = y * bitmapData.Stride + 3 * x;
暗示)。
修复上述错误后,您的过滤器可能仍然无法正常工作。调试或与此处的解决方案进行比较:C# Convolution filter for any size matrix (1x1, 3x3, 5x5, ...) not fully applied
以下例程仅锐化 8 位索引灰度。
public static Bitmap Sharpen(Bitmap image, double strength)
{
using (var bitmap1 = image as Bitmap)
{
if (bitmap1 != null)
{
var bitmap = bitmap1.Clone() as Bitmap;
int width = image.Width;
int height = image.Height;
// Create sharpening filter.
const int filterSize = 5;
var filter = new double[,]
{
{-1, -1, -1, -1, -1},
{-1, 2, 2, 2, -1},
{-1, 2, 16, 2, -1},
{-1, 2, 2, 2, -1},
{-1, -1, -1, -1, -1}
};
int channels = sizeof(byte);
double bias = 1.0 - strength;
double factor = strength / 16.0;
const int halfOfFilerSize = filterSize / 2;
byte[,] result = new byte[image.Width, image.Height];
// Lock image bits for read/write.
if (bitmap != null)
{
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite,
PixelFormat.Format8bppIndexed);
// Declare an array to hold the bytes of the bitmap.
int memorySize = bitmapData.Stride * height;
byte[] memory = new byte[memorySize];
// Copy the RGB values into the local array.
Marshal.Copy(bitmapData.Scan0, memory, 0, memorySize);
int rgb;
// Fill the color array with the new sharpened color values.
for (int y = halfOfFilerSize; y < height - halfOfFilerSize; y++)
{
for (int x = halfOfFilerSize; x < width - halfOfFilerSize; x++)
{
for (int filterY = 0; filterY < filterSize; filterY++)
{
double grayShade = 0.0;
for (int filterX = 0; filterX < filterSize; filterX++)
{
int imageX = (x - halfOfFilerSize + filterX + width) % width;
int imageY = (y - halfOfFilerSize + filterY + height) % height;
rgb = imageX * bitmapData.Stride + channels * imageY;
grayShade += memory[rgb + 0] * filter[filterX, filterY];
}
rgb = x * bitmapData.Stride + channels * y;
int b = Math.Min(Math.Max((int)(factor * grayShade + (bias * memory[rgb + 0])), 0), 255);
result[x, y] = (byte)b;
}
}
}
// Update the image with the sharpened pixels.
for (int x = halfOfFilerSize; x < width - halfOfFilerSize; x++)
{
for (int y = halfOfFilerSize; y < height - halfOfFilerSize; y++)
{
rgb = y * bitmapData.Stride + 3 * x;
memory[rgb + 0] = result[x, y];
}
}
// Copy the RGB values back to the bitmap.
Marshal.Copy(memory, 0, bitmapData.Scan0, memorySize);
// Release image bits.
bitmap.UnlockBits(bitmapData);
}
return bitmap;
}
}
return null;
}
此例程在以下行中抛出异常:
grayShade += memory[rgb + 0] * filter[filterX, filterY];
我哪里算错了?
.
.
P.S. 界面代码:
private void sharpenButton_Click(object sender, EventArgs e)
{
Bitmap sharpened = ImageSharpener.Sharpen(_inputImage, 0.5);
sharpenedPictureBox.Image = sharpened;
}
这个:
rgb = imageX * bitmapData.Stride + channels * imageY;
应该是:
rgb = imageY * bitmapData.Stride + channels * imageX;
还有这个:
rgb = x * bitmapData.Stride + channels * y;
应该是:
rgb = y * bitmapData.Stride + channels * x;
另外,你不应该乘以 channels
,那已经是 bitmapData.Stride
的一部分了。另外,请注意 channels = sizeof(byte)
,它只是 1,而不是 3(由 rgb = y * bitmapData.Stride + 3 * x;
暗示)。
修复上述错误后,您的过滤器可能仍然无法正常工作。调试或与此处的解决方案进行比较:C# Convolution filter for any size matrix (1x1, 3x3, 5x5, ...) not fully applied