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

news2024/11/26 11:49:28

在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#中实现图像的高斯模糊,对图像进行高斯模糊。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1849096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

碳+绿证如何能源匹配?考虑碳交易和绿证交易制度的电力批发市场能源优化程序代码!

前言 近年来&#xff0c;面对日益受到全社会关注的气候变化问题&#xff0c;国外尤其是欧美等发达国家和地区针对电力行业制定了一系列碳减排组合机制。其中&#xff0c;碳排放权交易&#xff08;以下简称“碳交易”&#xff09;和绿色电力证书交易&#xff08;以下简称“绿证…

JAVA医院绩效考核系统源码 功能特点:大型医院绩效考核系统源码

JAVA医院绩效考核系统源码 功能特点&#xff1a;大型医院绩效考核系统源码 医院绩效管理系统主要用于对科室和岗位的工作量、工作质量、服务质量进行全面考核&#xff0c;并对科室绩效工资和岗位绩效工资进行核算的系统。医院绩效管理系统开发主要用到的管理工具有RBRVS、DRGS…

【SCAU数据挖掘】数据挖掘期末总复习题库简答题及解析——下

1.从某超市顾客中随机抽取5名&#xff0c;他们的购物篮数据的二元0/1表示如下&#xff1a; 顾客号 面包 牛奶 尿布 啤酒 鸡蛋 可乐 1 1 1 0 0 0 0 2 1 0 1 1 1 0 3 0 1 1 1 0 1 4 1 1 1 1 0 0 5 1 1 1 0 0 1 某学生依据这些数据做…

【2024.6.22】今日科技时事:科技前沿大事件

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

《STM32 HAL库》CAN通信系列函数详尽解析——HAL_CAN_Init()

食用指南&#xff1a;本文主要内容为梳理CAN初始化函数主要运行逻辑及重点功能实现代码的详尽解析。函数源码在文末&#xff0c;建议在阅读源码之后观看。 CAN相关寄存器图&#xff1a; 主要逻辑分析&#xff1a; 下面分点梳理函数的主要逻辑&#xff08;注意逻辑序号&#xf…

为何云原生是未来?企业IT架构的颠覆与重构

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《未来已来&#xff1a;云原生之旅》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是云原生 2、云原生的背景和起源 背景 起源 关…

打字侠,中小学生暑期的打字练习神器

亲爱的家长们&#xff0c;暑假来临&#xff0c;孩子们又要开始“沙发上的咸鱼”模式了&#xff01;与其看着他们抱着手机、平板不放&#xff0c;不如让他们成为“打字侠”&#xff0c;在快乐中提升打字技能&#xff01; “打字侠”是一款为中小学生量身打造的打字练习神器。别…

WPF 程序 分布式 自动更新 登录 打包

服务器server端 core api 客户端WPF // 检查应用更新 //1、获取最新文件列表 // var files fileService.GetUpgradeFiles(); // 2、文件判断&#xff0c;新增的直接下载&#xff1b;更新的直接下载&#xff1b;删除的直接删除 // 客户端本地需要一个记录…

宇宙星空星辰美景素材哪里找?高清无水印分享

宇宙星空的美丽总能激发人们的无限遐想和灵感&#xff0c;不仅在科学教育领域&#xff0c;更在电影制作和视觉艺术中占有一席之地。为了帮助您找到高质量的宇宙星空视频素材&#xff0c;以下平台将成为您获取令人难忘天体视频素材的首选。 蛙学府 蛙学府作为新媒体创作者的宝库…

如何将图片转换为表格?方法并不难!

如何将图片转换为表格&#xff1f;在数字化时代&#xff0c;图片中的表格信息提取和整理成为了我们日常工作中不可或缺的一部分。不论是学术研究、商业分析还是个人生活&#xff0c;快速、准确地将图片转换为表格都显得尤为重要。今天&#xff0c;我们就来介绍四款强大的图片转…

经验总结--开关MOS管发热的一般原因/电源开发经验总结

开关MOS管发热的一般原因 做电源设计,或者做驱动方面的电路,难免要用到场效应管,也就是人们常说的MOS管。MOS管有很多种类,也有很多作用。做电源或者驱动的使用,当然就是用它的开关作用。 无论N型或者P型MOS管,其工作原理本质是一样的。MOS管是由加在输入端栅极的电压来控…

Android蓝牙开发(二)之蓝牙配对和蓝牙连接

BluetoothDevice.class.getMethod 进行配对&#xff0c;代码如下&#xff1a; Method method BluetoothDevice.class.getMethod(“createBond”); Log.e(getPackageName(), “开始配对”); method.invoke(listdevice.get(position)); invoke传的参数就是要配对的设备&…

ffmpeg音视频开发从入门到精通——ffmpeg日志及目录操作

文章目录 FFMPEG1. 操作日志2. 文件移动和删除3. 操作目录重要函数 FFMPEG 1. 操作日志 日志级别 AV LOG ERROR AV LOG WARNING AV LOG INFO AV LOG DEBUG cmake_minimum_required(VERSION 3.27) project(FFmpeg_exercise) set(CMAKE_CXX_STANDARD 14)# 定义FFmpeg的安装路…

Android自定义View之不得不知道的文件attrs

其中demo_style如下:一般都是放的.9图片&#xff0c;为了方便就放个颜色了 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190820183209784.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLm NzZG4ubmV0L3FxXzQyNzYxMz…

海外云手机自动化管理,高效省力解决方案

不论是企业还是个人&#xff0c;对于海外社媒的营销都是需要自动化管理的&#xff0c;因为自动化管理不仅省时省力&#xff0c;而且还节约成本&#xff1b; 海外云手机的自动化管理意味着什么&#xff1f;那就是企业无需再投入大量的人力和时间去逐一操作和监控每一台设备。 通…

鞋子分类数据集17399张69类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;17399 分类类别数&#xff1a;69 类别名称:[“0”,“1”,“2”,“3”,“4”…

全国实体商铺店铺商家采集工具,一键采集商家手机号,让你轻松找到目标客户

随着互联网的发展&#xff0c;越来越多的商家开始在网上开展业务&#xff0c;实体商铺的竞争也日益激烈。为了更好地吸引客户&#xff0c;很多商家都选择了线上推广和营销。然而&#xff0c;仅仅依靠线上推广是远远不够的&#xff0c;线下的实体商铺也需要积极拓展客源。因此&a…

DBeaver 数据结果集设置不显示逗号(太丑了)

从Navicat切换过来使用DBeaver&#xff0c;发现类似bigint 这种数据类型在结果集窗口中显示总是给我加上一个逗号&#xff0c;看着很不习惯&#xff0c;也比较占空间&#xff0c;个人觉得这种可读性也不好。 于是我在网上尝试搜索设置方法&#xff0c;可能我的关键词没命中&…

数据更新-插入元组(VALUES)、修改属性(SET)、删除元组(DELETE)

一、插入元组 1、插入单个元组&#xff08;使用的是VALUES子句&#xff09; &#xff08;1&#xff09;语句格式 INSERT INTO <表名> 【&#xff08;<属性名1【&#xff0c;<属性名2>&#xff0c;...】&#xff09;】 VALUES &#xff08;<常量1>【&a…

CATO原理中的数学与魔术(十四)——流程设计思路与升华

早点关注我&#xff0c;精彩不错过&#xff01; 系列终于进入尾声&#xff01;前面13篇文章已经穷尽搜刮掉我目力所及的全部CATO魔术的相关内容&#xff0c;并重新建立理论&#xff0c;分门别类进行了介绍。详情请戳&#xff1a; CATO原理中的数学与魔术&#xff08;十三&#…