I am trying to write a sobel filter.In a nutshell I should turn the image into the grayscale filter then I should apply sobel filter to the image.I found a code but I am not good at object oriented programming.How can I call the function when I push the button?
Here is the code:
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 }
};
}
}
}
}
I am trying to get the view from the camera with picfilte.Image.This is the part that I could not fill:
private void btnapply_Click(object sender, EventArgs e)
{
//How should I fill this part?
}
EDIT:The code is compiling if I write this code:
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 } });
}
}
CodePudding user response:
Assuming the Convolution method is correct, you should simply call it, something like
private void btnapply_Click(object sender, EventArgs e)
{
if(picoriginal.Image is Bitmap bitmap){
picfilte.Image = ConvolutionFilter(bitmap, xSobel, ySobel)
}
}