现在我先将这个链接下载下来:
现在我先将这个链接下载下来:
git clone https://github.com/Programming-With-Chris/OpenCVTutorials.git
先查看下面的代码:
csharp
using System;
using Emgu.CV;
namespace myNamespace
{
class Video1
{
static void Main(string[] args)
{
Mat pic = new Mat();
pic = CvInvoke.Imread("./img/starrynight.jpg");
Mat gaussianBlur = new Mat();
CvInvoke.GaussianBlur(pic, gaussianBlur, new System.Drawing.Size(3, 3), 7.0);
CvInvoke.Imshow("starry night", pic);
CvInvoke.Imshow("blurry night", gaussianBlur);
CvInvoke.WaitKey();
}
}
}
结合你是C# + Emgu CV(OpenCV C#封装) 小白的身份,我逐行拆解代码,从基础语法到OpenCV功能一步步讲,附带知识点、作用和注意事项。
完整代码逐行详解
csharp
// 1. 引入系统基础命名空间
using System;
解释
using是 C# 关键字,作用:导入现成的代码库/命名空间,不用重复写完整路径。System是 .NET 最核心的基础命名空间,包含字符串、基础数据类型、控制台等通用功能。- 本代码里虽然没直接用到它的复杂功能,但
Main入口方法、基础语法都依赖它,C#控制台程序几乎必加。
csharp
// 2. 引入Emgu CV核心命名空间(OpenCV C#版)
using Emgu.CV;
解释
Emgu.CV:Emgu CV 库的主命名空间,所有OpenCV图像、算法、工具函数都在这里。- 必须加这一行,否则代码里的
Mat、CvInvoke都会报"找不到类型"错误。 - 前提:你的项目已经安装了Emgu CV NuGet包,并配置好环境。
csharp
// 3. 自定义命名空间
namespace myNamespace
{
解释
namespace(命名空间):C# 用来分类、管理代码的容器,避免不同代码重名冲突。myNamespace是开发者自定义的名字,你可以改成任意英文名(比如CV_Demo、VideoTest)。- 大括号
{}:表示命名空间的代码范围,里面所有类、方法都属于这个空间。
csharp
// 4. 定义一个类
class Video1
{
解释
class:C# 定义类的关键字,类是C#代码的基本组织单元。Video1:类名,自定义名称,这里用来存放我们的图像处理逻辑。- 后续所有代码(入口方法、图像处理代码)都写在这个类内部。
csharp
// 5. 程序入口方法(整个程序从这里开始运行)
static void Main(string[] args)
{
解释
Main:C#控制台程序唯一入口,程序启动后第一行执行的代码就在这里。static:静态方法,程序启动时无需创建对象就能直接运行。void:表示这个方法没有返回值(执行完就结束,不返回数据)。string[] args:接收程序启动时传入的命令行参数,本案例用不到,可以保留也可以删掉。- 大括号
{}:方法体,所有图像处理代码都写在这里面。
csharp
// 6. 创建第一个Mat对象:用来存放原始图片
Mat pic = new Mat();
核心知识点:Mat
Mat 是 Emgu CV / OpenCV 最核心的图像容器 ,你可以把它理解为:专门存图片的"变量"。
Mat pic:定义一个名字叫pic的图像变量。new Mat():在内存中创建一个空的图像对象,此时里面还没有任何图片数据。- 作用:后续我们要把读取到的原图,存到
pic里面。
csharp
// 7. 读取本地图片,存入pic
pic = CvInvoke.Imread("./img/starrynight.jpg");
逐段拆解
CvInvoke:Emgu CV 调用原生 OpenCV 函数的静态工具类,绝大多数OpenCV功能都通过它调用。Imread():OpenCV 标准函数,功能:从电脑硬盘读取一张图片。- 参数
"./img/starrynight.jpg":图片路径./:代表当前程序运行目录(小白理解:exe文件所在的文件夹)。./img/:exe同级目录下的img文件夹。starrynight.jpg:要读取的图片文件名。
- 整行逻辑:读取
img文件夹下的starrynight.jpg,把图片数据赋值给pic。
💡 小白必看踩坑点:
- 必须保证 文件夹、图片名、后缀完全一致(区分大小写、格式 jpg/png 不能错);
- 路径错误会导致读取到空图片,运行后窗口黑屏/报错。
csharp
// 8. 创建第二个Mat对象:存放模糊后的图片
Mat gaussianBlur = new Mat();
解释
- 和第6行逻辑完全一样。
- 定义新的图像容器
gaussianBlur,专门用来接收高斯模糊处理后的新图片。 - OpenCV 处理图像原则:原图和结果图分开存储,不会直接修改原图。
csharp
// 9. 执行【高斯模糊】图像处理
CvInvoke.GaussianBlur(pic, gaussianBlur, new System.Drawing.Size(3, 3), 7.0);
重点详解(高斯模糊是常用图像降噪/磨皮算法)
GaussianBlur = 高斯模糊,作用:给图片做磨皮、降噪、柔化 。
函数一共4个参数,按顺序讲解:
- 第1个参数
pic:输入图像 = 要处理的原始图片。 - 第2个参数
gaussianBlur:输出图像 = 处理完成后,结果保存到这里。 - 第3个参数
new System.Drawing.Size(3, 3):卷积核大小(模糊窗口)- 格式必须是 奇数 × 奇数(3×3、5×5、7×7),不能用偶数;
- 数值越大,图片模糊程度越高;这里是 3像素×3像素 的模糊窗口。
- 第4个参数
7.0:高斯核标准差,控制模糊强度- 数值越大,模糊效果越强;0 表示由程序自动根据核大小计算。
总结这一行:把原图
pic做高斯模糊,结果存入gaussianBlur。
csharp
// 10. 弹出窗口,显示【原始图片】
CvInvoke.Imshow("starry night", pic);
解释
Imshow():OpenCV 专属函数,功能:新建窗口,展示图像 。
两个参数:
"starry night":窗口标题(字符串,自定义名字);pic:要显示的图像对象(这里是原图)。
运行后会弹出一个标题为starry night的窗口,展示原图。
csharp
// 11. 弹出窗口,显示【模糊后的图片】
CvInvoke.Imshow("blurry night", gaussianBlur);
解释
和上一行逻辑一致:
- 新建标题为
blurry night的窗口; - 展示经过高斯模糊处理后的图片。
此时桌面会同时出现两个图片窗口。
csharp
// 12. 等待按键输入,防止窗口一闪而过
CvInvoke.WaitKey();
小白核心必懂!
- 作用:暂停程序,等待你按下键盘任意按键。
- 如果删掉这行:程序跑完代码立刻结束,图片窗口一闪就关闭,根本看不到图片。
- 运行效果:图片窗口会一直停留,按键盘任意键后,窗口关闭、程序结束。
csharp
} // 结束 Main 方法
} // 结束 Video1 类
} // 结束 myNamespace 命名空间
解释
C# 大括号 {} 成对出现,分别闭合:方法、类、命名空间,保证代码结构完整。
一、整体程序运行流程(从头到尾梳理)
- 程序启动,进入
Main入口; - 创建空图像容器
pic; - 从本地文件夹读取图片,放入
pic; - 创建空图像容器
gaussianBlur,准备存处理后的图片; - 对原图执行高斯模糊 ,结果存入
gaussianBlur; - 弹出两个窗口,分别显示原图、模糊图;
- 暂停程序,等待按键;
- 按下按键 → 窗口关闭 → 程序运行结束。
二、小白常见问题 & 解决办法
- 运行后窗口黑屏、看不到图片?
→ 90%是图片路径错误 。检查:img文件夹是否和exe同级、图片名/后缀是否一致。 - 代码报"找不到Mat/CvInvoke"?
→ 没有正确安装/引用Emgu CVNuGet包。 - 图片窗口一闪而过?
→ 缺少CvInvoke.WaitKey()这一行。 Size(3,3)可以改吗?
→ 可以,只能改成奇数,比如(5,5),数值越大越模糊。
三、精简通俗总结
这段代码的功能非常简单:
读取一张本地图片 → 给图片做高斯模糊(磨皮)→ 同时显示原图和模糊图 → 按按键关闭窗口。