使用C#锐化位图

我想在图像上添加锐化滤镜。 我找到了一个简短教程的网站。 我试着在C#中这样做,所以这是我的代码。 无论如何,我试图找出它为什么不起作用。 我不知道我做错了什么,如果是的话,请告诉我该怎么做才能让它按原样运作。 谢谢

public static Bitmap sharpen(Bitmap image) { Bitmap sharpenImage = new Bitmap(image.Width, image.Height); int filterWidth = 3; int filterHeight = 3; int w = image.Width; int h = image.Height; double[,] filter = new double[filterWidth, filterHeight]; filter[0, 0] = filter[0, 1] = filter[0, 2] = filter[1, 0] = filter[1, 2] = filter[2, 0] = filter[2, 1] = filter[2, 2] = -1; filter[1, 1] = 9; double factor = 1.0; double bias = 0.0; Color[,] result = new Color[image.Width, image.Height]; for (int x = 0; x < w; ++x) { for (int y = 0; y < h; ++y) { double red = 0.0, green = 0.0, blue = 0.0; Color imageColor = image.GetPixel(x, y); for (int filterX = 0; filterX < filterWidth; filterX++) { for (int filterY = 0; filterY < filterHeight; filterY++) { int imageX = (x - filterWidth / 2 + filterX + w) % w; int imageY = (y - filterHeight / 2 + filterY + h) % h; red += imageColor.R * filter[filterX, filterY]; green += imageColor.G * filter[filterX, filterY]; blue += imageColor.B * filter[filterX, filterY]; } int r = Math.Min(Math.Max((int)(factor * red + bias), 0), 255); int g = Math.Min(Math.Max((int)(factor * green + bias), 0), 255); int b = Math.Min(Math.Max((int)(factor * blue + bias), 0), 255); result[x, y] = Color.FromArgb(r, g, b); } } } for (int i = 0; i < w; ++i) { for (int j = 0; j < h; ++j) { sharpenImage.SetPixel(i, j, result[i, j]); } } return sharpenImage; } 

 public static Bitmap sharpen(Bitmap image) { Bitmap sharpenImage = new Bitmap(image.Width, image.Height); int filterWidth = 3; int filterHeight = 3; int w = image.Width; int h = image.Height; double[,] filter = new double[filterWidth, filterHeight]; filter[0, 0] = filter[0, 1] = filter[0, 2] = filter[1, 0] = filter[1, 2] = filter[2, 0] = filter[2, 1] = filter[2, 2] = -1; filter[1, 1] = 9; double factor = 1.0; double bias = 0.0; Color[,] result = new Color[image.Width, image.Height]; for (int x = 0; x < w; ++x) { for (int y = 0; y < h; ++y) { double red = 0.0, green = 0.0, blue = 0.0; //=====[REMOVE LINES]======================================================== // Color must be read per filter entry, not per image pixel. Color imageColor = image.GetPixel(x, y); //=========================================================================== for (int filterX = 0; filterX < filterWidth; filterX++) { for (int filterY = 0; filterY < filterHeight; filterY++) { int imageX = (x - filterWidth / 2 + filterX + w) % w; int imageY = (y - filterHeight / 2 + filterY + h) % h; //=====[INSERT LINES]======================================================== // Get the color here - once per fiter entry and image pixel. Color imageColor = image.GetPixel(imageX, imageY); //=========================================================================== red += imageColor.R * filter[filterX, filterY]; green += imageColor.G * filter[filterX, filterY]; blue += imageColor.B * filter[filterX, filterY]; } int r = Math.Min(Math.Max((int)(factor * red + bias), 0), 255); int g = Math.Min(Math.Max((int)(factor * green + bias), 0), 255); int b = Math.Min(Math.Max((int)(factor * blue + bias), 0), 255); result[x, y] = Color.FromArgb(r, g, b); } } } for (int i = 0; i < w; ++i) { for (int j = 0; j < h; ++j) { sharpenImage.SetPixel(i, j, result[i, j]); } } return sharpenImage; } 

我采用了Daniel的答案,并通过使用BitmapData类对其性能进行了修改,因为使用GetPixel / SetPixel非常昂贵且不适合需要高性能的系统。 它与以前的解决方案完全相同,可以代替使用。

  public static Bitmap Sharpen(Bitmap image) { Bitmap sharpenImage = (Bitmap)image.Clone(); int filterWidth = 3; int filterHeight = 3; int width = image.Width; int height = image.Height; // Create sharpening filter. double[,] filter = new double[filterWidth, filterHeight]; filter[0, 0] = filter[0, 1] = filter[0, 2] = filter[1, 0] = filter[1, 2] = filter[2, 0] = filter[2, 1] = filter[2, 2] = -1; filter[1, 1] = 9; double factor = 1.0; double bias = 0.0; Color[,] result = new Color[image.Width, image.Height]; // Lock image bits for read/write. BitmapData pbits = sharpenImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // Declare an array to hold the bytes of the bitmap. int bytes = pbits.Stride * height; byte[] rgbValues = new byte[bytes]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(pbits.Scan0, rgbValues, 0, bytes); int rgb; // Fill the color array with the new sharpened color values. for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { double red = 0.0, green = 0.0, blue = 0.0; for (int filterX = 0; filterX < filterWidth; filterX++) { for (int filterY = 0; filterY < filterHeight; filterY++) { int imageX = (x - filterWidth / 2 + filterX + width) % width; int imageY = (y - filterHeight / 2 + filterY + height) % height; rgb = imageY * pbits.Stride + 3 * imageX; red += rgbValues[rgb + 2] * filter[filterX, filterY]; green += rgbValues[rgb + 1] * filter[filterX, filterY]; blue += rgbValues[rgb + 0] * filter[filterX, filterY]; } int r = Math.Min(Math.Max((int)(factor * red + bias), 0), 255); int g = Math.Min(Math.Max((int)(factor * green + bias), 0), 255); int b = Math.Min(Math.Max((int)(factor * blue + bias), 0), 255); result[x, y] = Color.FromArgb(r, g, b); } } } // Update the image with the sharpened pixels. for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { rgb = y * pbits.Stride + 3 * x; rgbValues[rgb + 2] = result[x, y].R; rgbValues[rgb + 1] = result[x, y].G; rgbValues[rgb + 0] = result[x, y].B; } } // Copy the RGB values back to the bitmap. System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, pbits.Scan0, bytes); // Release image bits. sharpenImage.UnlockBits(pbits); return sharpenImage; } 

这将产生更柔和的锐化效果。 如果需要,可以扩展滤镜arrays,或者将16更改为更大的滤镜arrays,但我发现这并不像你拥有的那样苛刻。

 const int filterWidth = 5; const int filterHeight = 5; double[,] filter = new double[filterWidth,filterHeight] { { -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 } }; double factor = 1.0 / 16.0; 

我结合了niaher和David的回答并修复了“偏见”属性。 现在,您可以将0.0和1.0之间的“强度”传递给Sharpen()函数。

 ///  /// Sharpens the specified image. ///  /// The image. /// The strength between 0.0 and 1.0. ///  public static Bitmap Sharpen(Image image, double strength) { using (var bitmap = image as Bitmap) { if (bitmap != null) { var sharpenImage = bitmap.Clone() as Bitmap; int width = image.Width; int height = image.Height; // Create sharpening filter. const int filterWidth = 5; const int filterHeight = 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} }; double bias = 1.0 - strength; double factor = strength/16.0; var result = new Color[image.Width,image.Height]; // Lock image bits for read/write. if (sharpenImage != null) { BitmapData pbits = sharpenImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // Declare an array to hold the bytes of the bitmap. int bytes = pbits.Stride*height; var rgbValues = new byte[bytes]; // Copy the RGB values into the array. Marshal.Copy(pbits.Scan0, rgbValues, 0, bytes); int rgb; // Fill the color array with the new sharpened color values. for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { double red = 0.0, green = 0.0, blue = 0.0; for (int filterX = 0; filterX < filterWidth; filterX++) { for (int filterY = 0; filterY < filterHeight; filterY++) { int imageX = (x - filterWidth/2 + filterX + width)%width; int imageY = (y - filterHeight/2 + filterY + height)%height; rgb = imageY*pbits.Stride + 3*imageX; red += rgbValues[rgb + 2]*filter[filterX, filterY]; green += rgbValues[rgb + 1]*filter[filterX, filterY]; blue += rgbValues[rgb + 0]*filter[filterX, filterY]; } rgb = y*pbits.Stride + 3*x; int r = Math.Min(Math.Max((int) (factor*red + (bias*rgbValues[rgb + 2])), 0), 255); int g = Math.Min(Math.Max((int) (factor*green + (bias*rgbValues[rgb + 1])), 0), 255); int b = Math.Min(Math.Max((int) (factor*blue + (bias*rgbValues[rgb + 0])), 0), 255); result[x, y] = Color.FromArgb(r, g, b); } } } // Update the image with the sharpened pixels. for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { rgb = y*pbits.Stride + 3*x; rgbValues[rgb + 2] = result[x, y].R; rgbValues[rgb + 1] = result[x, y].G; rgbValues[rgb + 0] = result[x, y].B; } } // Copy the RGB values back to the bitmap. Marshal.Copy(rgbValues, 0, pbits.Scan0, bytes); // Release image bits. sharpenImage.UnlockBits(pbits); } return sharpenImage; } } return null; } 

好的,用困难的边缘修复了问题。 这是更新的一个:

 ///  /// Sharpens the specified image. ///  /// The image. /// The strength. ///  public static Bitmap Sharpen(Image image, double strength) { using (var bitmap = image as Bitmap) { if (bitmap != null) { var sharpenImage = bitmap.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} }; double bias = 1.0 - strength; double factor = strength/16.0; const int s = filterSize/2; var result = new Color[image.Width,image.Height]; // Lock image bits for read/write. if (sharpenImage != null) { BitmapData pbits = sharpenImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // Declare an array to hold the bytes of the bitmap. int bytes = pbits.Stride*height; var rgbValues = new byte[bytes]; // Copy the RGB values into the array. Marshal.Copy(pbits.Scan0, rgbValues, 0, bytes); int rgb; // Fill the color array with the new sharpened color values. for (int x = s; x < width - s; x++) { for (int y = s; y < height - s; y++) { double red = 0.0, green = 0.0, blue = 0.0; for (int filterX = 0; filterX < filterSize; filterX++) { for (int filterY = 0; filterY < filterSize; filterY++) { int imageX = (x - s + filterX + width)%width; int imageY = (y - s + filterY + height)%height; rgb = imageY*pbits.Stride + 3*imageX; red += rgbValues[rgb + 2]*filter[filterX, filterY]; green += rgbValues[rgb + 1]*filter[filterX, filterY]; blue += rgbValues[rgb + 0]*filter[filterX, filterY]; } rgb = y * pbits.Stride + 3 * x; int r = Math.Min(Math.Max((int)(factor * red + (bias * rgbValues[rgb + 2])), 0), 255); int g = Math.Min(Math.Max((int)(factor * green + (bias * rgbValues[rgb + 1])), 0), 255); int b = Math.Min(Math.Max((int)(factor * blue + (bias * rgbValues[rgb + 0])), 0), 255); result[x, y] = Color.FromArgb(r, g, b); } } } // Update the image with the sharpened pixels. for (int x = s; x < width - s; x++) { for (int y = s; y < height - s; y++) { rgb = y*pbits.Stride + 3*x; rgbValues[rgb + 2] = result[x, y].R; rgbValues[rgb + 1] = result[x, y].G; rgbValues[rgb + 0] = result[x, y].B; } } // Copy the RGB values back to the bitmap. Marshal.Copy(rgbValues, 0, pbits.Scan0, bytes); // Release image bits. sharpenImage.UnlockBits(pbits); } return sharpenImage; } } return null; } 

嗨我编辑代码一点点,并为我添加另外两个矩阵这个现在完美的工作

 ///  /// Sharpens the specified image. ///  /// The image. /// strength erwartet werte zwische 0 - 99 ///  public Bitmap Sharpen(Image image, whichMatrix welcheMatrix , double strength) { double FaktorKorrekturWert = 0; //strenght muß für den jeweiligen filter angepasst werden switch (welcheMatrix) { case whichMatrix.Gaussian3x3: //diese Matrix benötigt einen strenght Wert von 0 bis -9.9 default ist -2.5 //und einen korekturwert von 16 strength = (strength * -1) / 10; FaktorKorrekturWert = 16; break; case whichMatrix.Mean3x3: //diese Matrix benötigt einen strenght Wert von 0 bis -9 default ist -2.25 //und einen Korrekturwert von 10 strength = strength * -9 / 100; FaktorKorrekturWert = 10; break; case whichMatrix.Gaussian5x5Type1: //diese Matrix benötigt einen strenght Wert von 0 bis 2.5 default ist 1.25 //und einen Korrekturwert von 12 strength = strength * 2.5 / 100; FaktorKorrekturWert = 12; break; default: break; } using (var bitmap = image as Bitmap) { if (bitmap != null) { var sharpenImage = bitmap.Clone() as Bitmap; int width = image.Width; int height = image.Height; // Create sharpening filter. var filter = Matrix(welcheMatrix); //const int filterSize = 3; // wenn die Matrix 3 Zeilen und 3 Spalten besitzt dann 3 bei 4 = 4 usw. int filterSize = filter.GetLength(0); double bias = 1.0 - strength; double factor = strength / FaktorKorrekturWert; //const int s = filterSize / 2; int s = filterSize / 2; // Filtersize ist keine Constante mehr darum wurde der befehl const entfernt var result = new Color[image.Width, image.Height]; // Lock image bits for read/write. if (sharpenImage != null) { BitmapData pbits = sharpenImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // Declare an array to hold the bytes of the bitmap. int bytes = pbits.Stride * height; var rgbValues = new byte[bytes]; // Copy the RGB values into the array. Marshal.Copy(pbits.Scan0, rgbValues, 0, bytes); int rgb; // Fill the color array with the new sharpened color values. for (int x = s; x < width - s; x++) { for (int y = s; y < height - s; y++) { double red = 0.0, green = 0.0, blue = 0.0; for (int filterX = 0; filterX < filterSize; filterX++) { for (int filterY = 0; filterY < filterSize; filterY++) { int imageX = (x - s + filterX + width) % width; int imageY = (y - s + filterY + height) % height; rgb = imageY * pbits.Stride + 3 * imageX; red += rgbValues[rgb + 2] * filter[filterX, filterY]; green += rgbValues[rgb + 1] * filter[filterX, filterY]; blue += rgbValues[rgb + 0] * filter[filterX, filterY]; } rgb = y * pbits.Stride + 3 * x; int r = Math.Min(Math.Max((int)(factor * red + (bias * rgbValues[rgb + 2])), 0), 255); int g = Math.Min(Math.Max((int)(factor * green + (bias * rgbValues[rgb + 1])), 0), 255); int b = Math.Min(Math.Max((int)(factor * blue + (bias * rgbValues[rgb + 0])), 0), 255); result[x, y] = System.Drawing.Color.FromArgb(r, g, b); } } } // Update the image with the sharpened pixels. for (int x = s; x < width - s; x++) { for (int y = s; y < height - s; y++) { rgb = y * pbits.Stride + 3 * x; rgbValues[rgb + 2] = result[x, y].R; rgbValues[rgb + 1] = result[x, y].G; rgbValues[rgb + 0] = result[x, y].B; } } // Copy the RGB values back to the bitmap. Marshal.Copy(rgbValues, 0, pbits.Scan0, bytes); // Release image bits. sharpenImage.UnlockBits(pbits); } return sharpenImage; } } return null; } public enum whichMatrix { Gaussian3x3, Mean3x3, Gaussian5x5Type1 } private double[,] Matrix(whichMatrix welcheMatrix) { double[,] selectedMatrix = null; switch (welcheMatrix) { case whichMatrix.Gaussian3x3: selectedMatrix = new double[,] { { 1, 2, 1, }, { 2, 4, 2, }, { 1, 2, 1, }, }; break; case whichMatrix.Gaussian5x5Type1: selectedMatrix = new double[,] { {-1, -1, -1, -1, -1}, {-1, 2, 2, 2, -1}, {-1, 2, 16, 2, -1}, {-1, 2, -1, 2, -1}, {-1, -1, -1, -1, -1} }; break; case whichMatrix.Mean3x3: selectedMatrix =new double[,] { { 1, 1, 1, }, { 1, 1, 1, }, { 1, 1, 1, }, }; break; } return selectedMatrix; }