1. 生成高斯核
首先,我们需要编写一个方法来生成高斯核。
public static float[,] creategaussiankernel(int length, float weight)
{
float[,] kernel = new float[length, length];
float sumtotal = 0;
int kernelradius = length / 2;
float distance = 0;
float calculatedeuler = 1.0f / (2.0f * (float)math.pi * weight * weight);
for (int filtery = -kernelradius; filtery <= kernelradius; filtery++)
{
for (int filterx = -kernelradius; filterx <= kernelradius; filterx++)
{
distance = ((filterx * filterx) + (filtery * filtery)) / (2 * (weight * weight));
kernel[filtery + kernelradius, filterx + kernelradius] = calculatedeuler * (float)math.exp(-distance);
sumtotal += kernel[filtery + kernelradius, filterx + kernelradius];
}
}
for (int y = 0; y < length; y++)
{
for (int x = 0; x < length; x++)
{
kernel[y, x] = kernel[y, x] * (1.0f / sumtotal);
}
}
return kernel;
}
2. 应用卷积滤波器
编写一个方法来应用卷积滤波器,将高斯核应用到图像上。
public static bitmap applyconvolutionfilter(bitmap sourceimage, float[,] kernel)
{
int width = sourceimage.width;
int height = sourceimage.height;
bitmapdata srcdata = sourceimage.lockbits(new rectangle(0, 0, width, height), imagelockmode.readonly, pixelformat.format32bppargb);
bitmap resultimage = new bitmap(width, height);
bitmapdata resultdata = resultimage.lockbits(new rectangle(0, 0, width, height), imagelockmode.writeonly, pixelformat.format32bppargb);
int bytesperpixel = 4;
int stride = srcdata.stride;
intptr srcscan0 = srcdata.scan0;
intptr resultscan0 = resultdata.scan0;
int kernelwidth = kernel.getlength(1);
int kernelheight = kernel.getlength(0);
int kerneloffset = kernelwidth / 2;
unsafe
{
byte* srcptr = (byte*)srcscan0.topointer();
byte* resultptr = (byte*)resultscan0.topointer();
for (int y = kerneloffset; y < height - kerneloffset; y++)
{
for (int x = kerneloffset; x < width - kerneloffset; x++)
{
float blue = 0.0f;
float green = 0.0f;
float red = 0.0f;
for (int ky = -kerneloffset; ky <= kerneloffset; ky++)
{
for (int kx = -kerneloffset; kx <= kerneloffset; kx++)
{
int pixelpos = ((y + ky) * stride) + ((x + kx) * bytesperpixel);
blue += srcptr[pixelpos] * kernel[ky + kerneloffset, kx + kerneloffset];
green += srcptr[pixelpos + 1] * kernel[ky + kerneloffset, kx + kerneloffset];
red += srcptr[pixelpos + 2] * kernel[ky + kerneloffset, kx + kerneloffset];
}
}
int resultpos = (y * stride) + (x * bytesperpixel);
resultptr[resultpos] = (byte)math.min(math.max(blue, 0), 255);
resultptr[resultpos + 1] = (byte)math.min(math.max(green, 0), 255);
resultptr[resultpos + 2] = (byte)math.min(math.max(red, 0), 255);
resultptr[resultpos + 3] = 255; // alpha channel
}
}
}
sourceimage.unlockbits(srcdata);
resultimage.unlockbits(resultdata);
return resultimage;
}
3. 使用高斯模糊处理图像
最后,编写一个程序来加载图像、应用高斯模糊滤波器,并保存处理后的图像。
using system;using system.drawing;using system.drawing.imaging;
class program
{
static void main()
{
// 加载原始图像
bitmap sourceimage = new bitmap("path_to_your_image.jpg");
// 创建高斯核
float weight = 1.0f;
int kernelsize = 5; // 核大小可以根据需要调整
float[,] kernel = creategaussiankernel(kernelsize, weight);
// 应用高斯模糊滤波器
bitmap resultimage = applyconvolutionfilter(sourceimage, kernel);
// 保存处理后的图像
resultimage.save("path_to_save_filtered_image.jpg");
}
public static float[,] creategaussiankernel(int length, float weight)
{
float[,] kernel = new float[length, length];
float sumtotal = 0;
int kernelradius = length / 2;
float distance = 0;
float calculatedeuler = 1.0f / (2.0f * (float)math.pi * weight * weight);
for (int filtery = -kernelradius; filtery <= kernelradius; filtery++)
{
for (int filterx = -kernelradius; filterx <= kernelradius; filterx++)
{
distance = ((filterx * filterx) + (filtery * filtery)) / (2 * (weight * weight));
kernel[filtery + kernelradius, filterx + kernelradius] = calculatedeuler * (float)math.exp(-distance);
sumtotal += kernel[filtery + kernelradius, filterx + kernelradius];
}
}
for (int y = 0; y < length; y++)
{
for (int x = 0; x < length; x++)
{
kernel[y, x] = kernel[y, x] * (1.0f / sumtotal);
}
}
return kernel;
}
public static bitmap applyconvolutionfilter(bitmap sourceimage, float[,] kernel)
{
int width = sourceimage.width;
int height = sourceimage.height;
bitmapdata srcdata = sourceimage.lockbits(new rectangle(0, 0, width, height), imagelockmode.readonly, pixelformat.format32bppargb);
bitmap resultimage = new bitmap(width, height);
bitmapdata resultdata = resultimage.lockbits(new rectangle(0, 0, width, height), imagelockmode.writeonly, pixelformat.format32bppargb);
int bytesperpixel = 4;
int stride = srcdata.stride;
intptr srcscan0 = srcdata.scan0;
intptr resultscan0 = resultdata.scan0;
int kernelwidth = kernel.getlength(1);
int kernelheight = kernel.getlength(0);
int kerneloffset = kernelwidth / 2;
unsafe
{
byte* srcptr = (byte*)srcscan0.topointer();
byte* resultptr = (byte*)resultscan0.topointer();
for (int y = kerneloffset; y < height - kerneloffset; y++)
{
for (int x = kerneloffset; x < width - kerneloffset; x++)
{
float blue = 0.0f;
float green = 0.0f;
float red = 0.0f;
for (int ky = -kerneloffset; ky <= kerneloffset; ky++)
{
for (int kx = -kerneloffset; kx <= kerneloffset; kx++)
{
int pixelpos = ((y + ky) * stride) + ((x + kx) * bytesperpixel);
blue += srcptr[pixelpos] * kernel[ky + kerneloffset, kx + kerneloffset];
green += srcptr[pixelpos + 1] * kernel[ky + kerneloffset, kx + kerneloffset];
red += srcptr[pixelpos + 2] * kernel[ky + kerneloffset, kx + kerneloffset];
}
}
int resultpos = (y * stride) + (x * bytesperpixel);
resultptr[resultpos] = (byte)math.min(math.max(blue, 0), 255);
resultptr[resultpos + 1] = (byte)math.min(math.max(green, 0), 255);
resultptr[resultpos + 2] = (byte)math.min(math.max(red, 0), 255);
resultptr[resultpos + 3] = 255; // alpha channel
}
}
}
sourceimage.unlockbits(srcdata);
resultimage.unlockbits(resultdata);
return resultimage;
}
}
图像对比
- 原图:
- 处理后:
注意事项
- 确保路径 path_to_your_image.jpg 和 path_to_save_filtered_image.jpg 是正确的。
- 调整高斯核的大小和权重以获得所需的模糊效果。
- system.drawing。
发表评论