如何在 C# 中调用 Sobel 滤波器和图像处理函数

How can I call the function for Sobel filter,Image processing in C#

我正在尝试写一个 sobel filter.In 简而言之,我应该将图像转换为灰度滤镜然后我应该将 sobel 滤镜应用于 image.I 找到了一个代码,但我不擅长面向对象 programming.How 我可以在按下按钮时调用函数吗?

代码如下:

using AForge.Video.DirectShow;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace dnm1110
{
   public partial class Form1 : Form
   {
       public Form1()
       {
           InitializeComponent();
       }
       public FilterInfoCollection devices;
       public VideoCaptureDevice camera;
       private void Form1_Load(object sender, EventArgs e)
       {
           devices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

           foreach (FilterInfo item in devices)
           {
               comboBox1.Items.Add(item.Name);

           }

           camera = new VideoCaptureDevice();

           comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
       }

       private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
       {
           try
           {

               if (camera.IsRunning == false)

               {

                   camera = new VideoCaptureDevice(devices[comboBox1.SelectedIndex].MonikerString);

                   camera.NewFrame += Camera_NewFrame;

                   camera.Start();

               }

           }

           catch (Exception exc)

           {
               MessageBox.Show(exc.Message + "");
           }
       }
       private void Camera_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
       {
           Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone();

           picoriginal.Image = bitmap;
       }

       private void btnapply_Click(object sender, EventArgs e)
       {
           
       }
           private static Bitmap ConvolutionFilter(Bitmap bitmap,double[,] xkernel, double[,] ykernel, double factor = 1, int bias = 0, bool grayscale = false)
           {

               //Image dimensions stored in variables for convenience
               int width = bitmap.Width;
               int height = bitmap.Height;

               //Lock source image bits into system memory
               BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

               //Get the total number of bytes in your image - 32 bytes per pixel x image width x image height -> for 32bpp images
               int bytes = bmpData.Stride * bmpData.Height;

               //Create byte arrays to hold pixel information of your image
               byte[] pixelBuffer = new byte[bytes];
               byte[] bitmap2Buffer = new byte[bytes];

               //Get the address of the first pixel data
               IntPtr srcScan0 = bmpData.Scan0;

               //Copy image data to one of the byte arrays
               Marshal.Copy(srcScan0, pixelBuffer, 0, bytes);

               //Unlock bits from system memory -> we have all our needed info in the array
               bitmap.UnlockBits(bmpData);
               //Convert your image to grayscale if necessary
               if (grayscale == true)
               {
                   float rgb = 0;
                   for (int i = 0; i < pixelBuffer.Length; i += 4)
                   {
                       rgb = pixelBuffer[i] * .21f;
                       rgb += pixelBuffer[i + 1] * .71f;
                       rgb += pixelBuffer[i + 2] * .071f;
                       pixelBuffer[i] = (byte)rgb;
                       pixelBuffer[i + 1] = pixelBuffer[i];
                       pixelBuffer[i + 2] = pixelBuffer[i];
                       pixelBuffer[i + 3] = 255;
                   }
               }
               //Create variable for pixel data for each kernel
               double xr = 0.0;
               double xg = 0.0;
               double xb = 0.0;
               double yr = 0.0;
               double yg = 0.0;
               double yb = 0.0;
               double rt = 0.0;
               double gt = 0.0;
               double bt = 0.0;

               //This is how much your center pixel is offset from the border of your kernel
               //Sobel is 3x3, so center is 1 pixel from the kernel border
               int filterOffset = 1;
               int calcOffset = 0;
               int byteOffset = 0;

               //Start with the pixel that is offset 1 from top and 1 from the left side
               //this is so entire kernel is on your image
               for (int OffsetY = filterOffset; OffsetY < height - filterOffset; OffsetY++)
               {
                   for (int OffsetX = filterOffset; OffsetX < width - filterOffset; OffsetX++)
                   {
                       //reset rgb values to 0
                       xr = xg = xb = yr = yg = yb = 0;
                       rt = gt = bt = 0.0;

                       //position of the kernel center pixel
                       byteOffset = OffsetY * bmpData.Stride + OffsetX * 4;
                       //kernel calculations
                       for (int filterY = -filterOffset; filterY <= filterOffset; filterY++)
                       {
                           for (int filterX = -filterOffset; filterX <= filterOffset; filterX++)
                           {
                               calcOffset = byteOffset + filterX * 4 + filterY * bmpData.Stride;
                               xb += (double)(pixelBuffer[calcOffset]) * xkernel[filterY + filterOffset, filterX + filterOffset];
                               xg += (double)(pixelBuffer[calcOffset + 1]) * xkernel[filterY + filterOffset, filterX + filterOffset];
                               xr += (double)(pixelBuffer[calcOffset + 2]) * xkernel[filterY + filterOffset, filterX + filterOffset];
                               yb += (double)(pixelBuffer[calcOffset]) * ykernel[filterY + filterOffset, filterX + filterOffset];
                               yg += (double)(pixelBuffer[calcOffset + 1]) * ykernel[filterY + filterOffset, filterX + filterOffset];
                               yr += (double)(pixelBuffer[calcOffset + 2]) * ykernel[filterY + filterOffset, filterX + filterOffset];
                           }
                       }

                       //total rgb values for this pixel
                       bt = Math.Sqrt((xb * xb) + (yb * yb));
                       gt = Math.Sqrt((xg * xg) + (yg * yg));
                       rt = Math.Sqrt((xr * xr) + (yr * yr));

                       //set limits, bytes can hold values from 0 up to 255;
                       if (bt > 255) bt = 255;
                       else if (bt < 0) bt = 0;
                       if (gt > 255) gt = 255;
                       else if (gt < 0) gt = 0;
                       if (rt > 255) rt = 255;
                       else if (rt < 0) rt = 0;

                       //set new data in the other byte array for your image data
                       bitmap2Buffer[byteOffset] = (byte)(bt);
                       bitmap2Buffer[byteOffset + 1] = (byte)(gt);
                       bitmap2Buffer[byteOffset + 2] = (byte)(rt);
                       bitmap2Buffer[byteOffset + 3] = 255;
                   }
               }
               //Create new bitmap which will hold the processed data
               Bitmap bitmap2 = new Bitmap(width, height);

               //Lock bits into system memory
               BitmapData bmp2Data = bitmap2.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

               //Copy from byte array that holds processed data to bitmap
               Marshal.Copy(bitmap2Buffer, 0, bmp2Data.Scan0, bitmap2Buffer.Length);

               //Unlock bits from system memory
               bitmap2.UnlockBits(bmp2Data);

               //Return processed image
               return bitmap2;
           }
                      //Sobel operator kernel for horizontal pixel changes
                      private static double[,] xSobel
                      {
                          get
                          {
                               return new double[,]
                               {
                                   { -1, 0, 1 },
                                   { -2, 0, 2 },
                                   { -1, 0, 1 }
                               };
                          }
                      }

                            //Sobel operator kernel for vertical pixel changes
                                private static double[,] ySobel
                                {
                                     get
                                     {
                                             return new double[,]
                                             {
                                                  {  1,  2,  1 },
                                                  {  0,  0,  0 },
                                                  { -1, -2, -1 }
                                             };
                                     }
                                }
   }
}


我正在尝试从相机获取视图 picfilte.Image.This 是我无法填充的部分:

 private void btnapply_Click(object sender, EventArgs e)
        {
            //How should I fill this part?
        }

编辑:如果我写这段代码,代码正在编译:

private void btnapply_Click(object sender, EventArgs e)
        {
            if (picoriginal.Image is Bitmap image)
            {
                picfilter.Image = ConvolutionFilter(image, new double[3, 3] { { -1, -2, -1 }, { 0, 0, 0 },{ 1, 2, 1 } }, new double[3, 3] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } });
            }
        }

假设卷积方法是正确的,你应该简单地调用它,比如

private void btnapply_Click(object sender, EventArgs e)
{
   if(picoriginal.Image is Bitmap bitmap){
          picfilte.Image = ConvolutionFilter(bitmap, xSobel, ySobel)
   }
}