OpencvSharp 算子学习教案之 - Cv2.Resize
大家好,Opencv在很多工程项目中都会用到,而OpencvSharp则是以C#开发与实现的Opencv操作库,对.NET开发人员友好,但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳,因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案,供大家参考学习。
Cv2.Resize
- 教案版本:V1.0
- 面向对象:OpenCvSharp 初学者
- 所属模块:imgproc
- 源码位置:OpenCvSharp/Cv2/Cv2_imgproc.cs:991
摘要:Cv2.Resize 会按目标尺寸或缩放比例重新采样图像。本文通过尺寸对照、插值说明和 WPF 场景演示,帮助初学者看懂 dsize、fx/fy 和不同插值方式各自负责什么。
1. 函数名称(带参数签名)
publicstaticvoidResize(InputArraysrc,OutputArraydst,Sizedsize,doublefx=0,doublefy=0,InterpolationFlagsinterpolation=InterpolationFlags.Linear)2. 函数用途
Cv2.Resize的作用,是把输入图像重新采样成新的大小。
它最常见的用途有:
- 把图片缩小后用于预览、搜索或网络传输。
- 把图片放大后用于显示、排版或后处理。
- 在深度学习前处理里统一输入尺寸。
- 在界面开发里把图像适配到固定显示区域。
这个函数并不只是“拉伸图片”。它会按照插值规则计算新像素,因此缩小和放大时的视觉效果会不同。
3. 函数公式
如果dsize为空,常见理解方式是按缩放比例采样:
x s = x d f x , y s = y d f y x_s = \frac{x_d}{fx}, \qquad y_s = \frac{y_d}{fy}xs=fxxd,ys=fyyd
然后从源图像的(x_s, y_s)位置取样并写入目标图像。
如果dsize指定了目标尺寸,那么 OpenCvSharp 会根据目标尺寸和插值方式完成重采样。
当缩小图像时,INTER_AREA通常更自然;当放大图像时,INTER_LINEAR和INTER_CUBIC更常见。
4. 函数原理说明
Resize的本质是“输出图像每个像素,到源图像哪里取值”。
- 先确定输出尺寸。
- 再根据
dsize或fx/fy计算映射关系。 - 对每个输出像素做插值采样。
- 把结果写入
dst。
初学者最容易弄混的地方是:
- 以为
fx/fy和dsize会同时强制生效,其实通常是按调用方式决定输出尺寸。 - 把缩小也当成简单抽样,结果图像会出现锯齿或失真。
- 把放大和缩小都用同一种插值,导致细节不理想。
本页的 WPF 场景会把固定尺寸、缩小和放大放在一起对比,帮助你建立直观感受。
5. 参数含义解析
| 参数名 | 类型 | 必填 | 含义 |
|---|---|---|---|
| src | InputArray | 是 | 输入图像 |
| dst | OutputArray | 是 | 输出图像 |
| dsize | Size | 是 | 目标尺寸 |
| fx | double | 否 | 水平缩放比例 |
| fy | double | 否 | 垂直缩放比例 |
| interpolation | InterpolationFlags | 否 | 插值方式 |
补充说明:
dsize.Width和dsize.Height直接决定输出图像大小。fx和fy更适合“按比例缩放”的写法。INTER_AREA常用于缩小,INTER_LINEAR常用于放大。- 输出图像的通道数和类型通常保持与源图像一致。
6. 应用场景列表
| 场景名 | 场景说明 | 典型用途 |
|---|---|---|
| 场景A:固定尺寸缩放 | 直接指定目标宽高 | UI 适配、统一输入 |
| 场景B:缩小预览图 | 按比例压缩图像 | 预览、缓存、传输 |
| 场景C:放大细节图 | 按比例放大图像 | 显示、观察局部细节 |
| 场景D:插值对比 | 比较不同插值的效果 | 教学、调参与分析 |
7. 函数使用示例
下面的 Console 程序演示Resize的三种常见写法:固定尺寸、缩小和放大。示例使用一个小矩阵,便于观察重采样后的结果。
usingSystem;usingSystem.Text;usingOpenCvSharp;internalstaticclassProgram{/// <summary>/// 程序入口。/// </summary>privatestaticvoidMain(){// 中文输出要切到 UTF-8,避免说明文字乱码。Console.OutputEncoding=Encoding.UTF8;usingvarsource=CreateSourceMatrix();usingvarfixedSize=newMat();usingvarhalfSize=newMat();usingvarenlargeSize=newMat();// 固定尺寸写法:直接指定目标宽高。Cv2.Resize(source,fixedSize,newSize(6,4),0,0,InterpolationFlags.Nearest);// 缩小写法:用 fx / fy 传入比例。Cv2.Resize(source,halfSize,newSize(),0.5,0.5,InterpolationFlags.Area);// 放大写法:同样可以用 fx / fy 传入比例。Cv2.Resize(source,enlargeSize,newSize(),1.5,1.5,InterpolationFlags.Linear);PrintMat("原图",source);PrintMat("固定尺寸 6x4",fixedSize);PrintMat("0.5x 缩小",halfSize);PrintMat("1.5x 放大",enlargeSize);}/// <summary>/// 创建一个单通道测试矩阵。/// </summary>/// <returns>4x4 灰度矩阵。</returns>privatestaticMatCreateSourceMatrix(){// 这里故意用简单的递增数字,方便观察像素被如何重新采样。varsource=newMat(4,4,MatType.CV_8UC1);bytevalue=10;for(varrow=0;row<source.Rows;row++){for(varcol=0;col<source.Cols;col++){// 逐格赋值,便于对照输出结果。source.At<byte>(row,col)=value;value+=10;}}returnsource;}/// <summary>/// 打印单通道矩阵。/// </summary>/// <param name="title">标题。</param>/// <param name="mat">矩阵。</param>privatestaticvoidPrintMat(stringtitle,Matmat){Console.WriteLine(title);for(varrow=0;row<mat.Rows;row++){for(varcol=0;col<mat.Cols;col++){// 这里直接打印每个像素值,方便初学者看懂尺寸变化后的重采样结果。Console.Write($"{mat.At<byte>(row,col),4}");}Console.WriteLine();}Console.WriteLine();}}8. 注意事项
Resize修改的是图像尺寸,不是窗口尺寸。- 缩小时最好考虑
INTER_AREA。 - 放大时最好考虑
INTER_LINEAR或INTER_CUBIC。 - 如果输出尺寸和输入尺寸差别很大,细节变化会很明显。
9. 调优建议
- 如果你已经有目标尺寸,优先使用
dsize写法。 - 如果你是在做比例缩放,优先使用
fx/fy写法。 - 做教学对比时,把原图、缩小图和放大图放在一起更容易讲清楚。
- 在工程里统一插值方式,可以减少视觉风格不一致的问题。
10. 运行说明
- 如果你在控制台工程里运行本文示例,直接把代码放进
Program.cs即可。 - 如果你在本仓库里学习,请打开 WPF 控件 Cv2ResizeControl.xaml.cs 对应的页面。
- 点击“运行场景A”,可以看到固定尺寸、缩小和放大的教学对比。
11. 常见错误排查
- 把
dsize设成空尺寸,却又误以为输出一定跟输入一样大。 - 缩小图像时使用不合适的插值,结果出现锯齿或细节丢失。
- 把
fx和fy写成 0,却没有真正提供目标尺寸。 - 把
Resize和窗口大小调整函数混淆。