2009-05-24 26 views
13

Tôi muốn đặt bộ lọc sắc nét lên hình ảnh. Tôi đã tìm thấy một trang web with short tutorial. Tôi đã cố gắng làm điều đó trong C# vì vậy đây là mã của tôi. Dù sao, tôi đã cố gắng tìm hiểu lý do tại sao nó không hoạt động. Tôi không biết nếu tôi đang làm điều gì đó sai, nếu có, xin vui lòng tư vấn cho tôi những gì phải làm để làm cho nó hoạt động như nó phải. Cảm ơnLàm sắc nét trên một Bitmap bằng 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; 
    } 
+0

Có chương thú vị của "mã đẹp" bằng văn bản của Charles Petzold có tên là "Mã phát trực tuyến để xử lý hình ảnh". Bạn có thể thấy nó rất hữu ích. – okutane

Trả lời

25
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; 
} 
+1

Cảm ơn bạn, câu trả lời của bạn thực sự hữu ích – Allek

23

tôi lấy câu trả lời của Daniel và sửa đổi nó cho hiệu suất, bằng cách sử dụng lớp BitmapData, kể từ khi sử dụng GetPixel/SetPixel là rất tốn kém và không phù hợp cho các hệ thống hiệu suất đói. Nó hoạt động chính xác giống như giải pháp trước và có thể được sử dụng thay thế.

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; 
    } 
7

Điều này sẽ tạo ra hiệu ứng mài nhẹ nhàng hơn. Bạn có thể mở rộng mảng bộ lọc nếu cần, hoặc thay đổi 16 thành cái gì đó lớn hơn, nhưng tôi thấy điều này không quá khắc nghiệt như cái bạn có.

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; 
3

Tôi kết hợp câu trả lời của niaher và David và cố định thuộc tính "thiên vị". Bây giờ bạn có thể vượt qua một "sức mạnh" giữa 0,0 và 1,0 đến hàm Sharpen().

/// <summary> 
///  Sharpens the specified image. 
/// </summary> 
/// <param name="image">The image.</param> 
/// <param name="strength">The strength between 0.0 and 1.0.</param> 
/// <returns></returns> 
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; 
} 
3

Ok, đã khắc phục sự cố với các cạnh bị phân tán. Here's các cập nhật một:

/// <summary> 
/// Sharpens the specified image. 
/// </summary> 
/// <param name="image">The image.</param> 
/// <param name="strength">The strength.</param> 
/// <returns></returns> 
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; 
} 
1

hi i chỉnh sửa mã một chút litle và thêm hai ma trận khác đối với tôi đây làm việc tại hoàn hảo

/// <summary> 
    /// Sharpens the specified image. 
    /// </summary> 
    /// <param name="image">The image.</param> 
    /// <param name="strength">strength erwartet werte zwische 0 - 99</param> 
    /// <returns></returns> 
    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; 
    } 
+0

aaalter chỉnh sửa mã trong deutsch und englisch gleichezitig? idlechte idee ^^ –

Các vấn đề liên quan