C#实现高斯模糊(图像处理)

在C#中实现高斯模糊,可以使用System.Drawing库。高斯模糊是一种基于高斯函数的滤波器,它可以有效地平滑图像。以下是详细的步骤,包括生成高斯核并应用到图像上的代码示例。

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。

通过上述步骤,你可以在C#中实现图像的高斯模糊,对图像进行高斯模糊。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用C#实现高斯消元法来求解矩阵的逆,可以按照以下步骤进行操作: 1. 创建一个表示矩阵的二维数组。 2. 创建一个与矩阵大小相同的单位矩阵。 3. 执行高斯消元法的步骤,将矩阵转化为上三角矩阵,并同时对单位矩阵进行相同的操作。 4. 执行回代操作,将上三角矩阵转化为对角矩阵,同时对单位矩阵进行相同的操作。 5. 对对角矩阵中的每个元素进行归一化,同时对单位矩阵进行相同的操作。 6. 返回得到的逆矩阵。 以下是一个示例代码: ```csharp public class MatrixInverseExample { public static double[][] MatrixInverse(double[][] matrix) { int n = matrix.Length; double[][] augmentedMatrix = new double[n][]; // 创建一个与原始矩阵大小相同的单位矩阵 for (int i = 0; i < n; i++) { augmentedMatrix[i] = new double[2 * n]; augmentedMatrix[i][i + n] = 1; for (int j = 0; j < n; j++) { augmentedMatrix[i][j] = matrix[i][j]; } } // 高斯消元法转化为上三角矩阵 for (int i = 0; i < n; i++) { double pivot = augmentedMatrix[i][i]; for (int j = i + 1; j < 2 * n; j++) { augmentedMatrix[i][j] /= pivot; } for (int j = 0; j < n; j++) { if (j != i) { double factor = augmentedMatrix[j][i]; for (int k = i + 1; k < 2 * n; k++) { augmentedMatrix[j][k] -= factor * augmentedMatrix[i][k]; } } } } // 回代转化为对角矩阵 for (int i = n - 1; i >= 0; i--) { for (int j = 0; j < n; j++) { if (j != i) { double factor = augmentedMatrix[j][i]; for (int k = i; k < 2 * n; k++) { augmentedMatrix[j][k] -= factor * augmentedMatrix[i][k]; } } } } // 归一化对角矩阵的每个元素 for (int i = 0; i < n; i++) { double pivot = augmentedMatrix[i][i]; for (int j = i; j < 2 * n; j++) { augmentedMatrix[i][j] /= pivot; } } // 提取逆矩阵 double[][] inverseMatrix = new double[n][]; for (int i = 0; i < n; i++) { inverseMatrix[i] = new double[n]; for (int j = 0; j < n; j++) { inverseMatrix[i][j] = augmentedMatrix[i][j + n]; } } return inverseMatrix; } public static void Main() { // 创建一个2x2的矩阵 double[][] matrix = new double[][] { new double[] { 1, 2 }, new double[] { 3, 4 } }; // 求逆 double[][] inverseMatrix = MatrixInverse(matrix); // 打印结果 Console.WriteLine("原始矩阵:"); PrintMatrix(matrix); Console.WriteLine(); Console.WriteLine("逆矩阵:"); PrintMatrix(inverseMatrix); } public static void PrintMatrix(double[][] matrix) { int n = matrix.Length; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Console.Write(matrix[i][j] + " "); } Console.WriteLine(); } } } ``` 这个示例中,我们定义了一个MatrixInverse()方法来执行矩阵求逆的操作。在Main()方法中,我们创建一个2x2的矩阵,并调用MatrixInverse()方法来计算逆矩阵。最后,我们使用PrintMatrix()方法来打印原始矩阵和逆矩阵。 输出结果应该为: ``` 原始矩阵: 1 2 3 4 逆矩阵: -2.0000000000000004 1.0000000000000002 1.5000000000000002 -0.5000000000000002 ``` 请注意,由于浮点数计算的精度问题,逆矩阵中的元素可能不会完全等于预期值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新鑫S

你的鼓励将是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值