news 2026/4/21 19:12:28

OpencvSharp 算子学习教案之 - Cv2.WarpAffine

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpencvSharp 算子学习教案之 - Cv2.WarpAffine

OpencvSharp 算子学习教案之 - Cv2.WarpAffine

大家好,Opencv在很多工程项目中都会用到,而OpencvSharp则是以C#开发与实现的Opencv操作库,对.NET开发人员友好,但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳,因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案,供大家参考学习。

Cv2.WarpAffine

  • 教案版本:V1.0
  • 面向对象:OpenCvSharp 初学者
  • 所属模块:imgproc
  • 源码位置:OpenCvSharp/Cv2/Cv2_imgproc.cs:1022

摘要:Cv2.WarpAffine 用 2x3 仿射矩阵把图像重新采样到新的位置。本文通过旋转、平移和错切三个关键词拆解矩阵含义,并配合 WPF 场景帮助初学者把公式和图像结果对上号。

1. 函数名称(带参数签名)

publicstaticvoidWarpAffine(InputArraysrc,OutputArraydst,InputArraym,Sizedsize,InterpolationFlagsflags=InterpolationFlags.Linear,BorderTypesborderMode=BorderTypes.Constant,Scalar?borderValue=null)

2. 函数用途

Cv2.WarpAffine的作用,是把图像按 2x3 仿射矩阵做几何变换。

它最常见的用途有:

  1. 做旋转、缩放和平移的组合变换。
  2. 做错切和轻微校正。
  3. 在数据增强中模拟相机角度变化。
  4. 在图像预处理里做坐标统一。

这个函数比Resize更通用,因为它不是只改尺寸,而是可以同时改变方向、位置和比例。

3. 函数公式

仿射矩阵可以直接写成矩阵乘法:

x ′ = m 00 x + m 01 y + m 02 y ′ = m 10 x + m 11 y + m 12 \begin{aligned} x' &= m_{00}x + m_{01}y + m_{02} \\ y' &= m_{10}x + m_{11}y + m_{12} \end{aligned}xy=m00x+m01y+m02=m10x+m11y+m12

这里的m就是 2x3 仿射矩阵。上面的矩阵形式和展开形式,分别说明了输出坐标如何由源坐标xy计算得到。

需要注意的是,OpenCV 在实现时通常会使用逆向映射,也就是从输出像素反推它应该从源图像哪里取值。

4. 函数原理说明

WarpAffine的本质,是把一个二维坐标变换应用到整张图像上。

  1. 先读取 2x3 矩阵。
  2. 再把输出图像中的每个像素映射回源图像。
  3. 对回到源图像的坐标做插值。
  4. 把结果写入目标图像。

初学者最容易混淆的地方是:

  1. 把仿射变换和透视变换混为一谈。
  2. 忘记WarpAffine需要一个 2x3 矩阵,而不是 3x3 矩阵。
  3. 只会旋转,不知道平移和错切也属于仿射变换。
  4. 忽略插值和边界模式对边缘像素的影响。

本页的 WPF 场景会同时展示旋转矩阵和错切矩阵,帮助你分清不同参数的作用。

5. 参数含义解析

参数名类型必填含义
srcInputArray输入图像
dstOutputArray输出图像
mInputArray2x3 仿射矩阵
dsizeSize目标尺寸
flagsInterpolationFlags插值方式
borderModeBorderTypes边界模式
borderValueScalar?常量边界值

补充说明:

  1. m里的六个值会共同决定图像如何移动和变形。
  2. dsize只决定输出图像大小,不负责决定变换内容。
  3. 如果输出区域超出源图范围,需要结合borderMode理解边缘行为。
  4. 仿射变换不产生透视消失点。

6. 应用场景列表

场景名场景说明典型用途
场景A:轻微旋转图像绕中心小角度旋转对齐、增强
场景B:平移校正把图像整体挪动到合适位置裁切、定位
场景C:错切变换让图像发生斜切教学、特效
场景D:组合变换把旋转和缩放叠加视觉处理、增强

7. 函数使用示例

下面的 Console 程序演示两个仿射矩阵:一个来自GetRotationMatrix2D,另一个是手写的错切矩阵。这样更容易看出WarpAffine负责的是“执行变换”,而不是“生成矩阵”。

usingSystem;usingSystem.Text;usingOpenCvSharp;internalstaticclassProgram{/// <summary>/// 程序入口。/// </summary>privatestaticvoidMain(){// 控制台输出切到 UTF-8,避免中文说明乱码。Console.OutputEncoding=Encoding.UTF8;usingvarsource=CreateSourceImage();usingvarrotationMatrix=Cv2.GetRotationMatrix2D(newPoint2f(2f,2f),-15,1.0);usingvarshearMatrix=CreateShearMatrix();usingvarrotated=newMat();usingvarsheared=newMat();// 先演示旋转仿射矩阵的效果。Cv2.WarpAffine(source,rotated,rotationMatrix,source.Size(),InterpolationFlags.Nearest,BorderTypes.Constant,Scalar.All(0));// 再演示错切矩阵的效果。Cv2.WarpAffine(source,sheared,shearMatrix,source.Size(),InterpolationFlags.Nearest,BorderTypes.Constant,Scalar.All(0));Console.WriteLine("源图:");PrintMat(source);Console.WriteLine("旋转矩阵:");PrintMat(rotationMatrix);Console.WriteLine("旋转结果:");PrintMat(rotated);Console.WriteLine("错切矩阵:");PrintMat(shearMatrix);Console.WriteLine("错切结果:");PrintMat(sheared);}/// <summary>/// 创建一个单通道测试图。/// </summary>/// <returns>5x5 灰度图。</returns>privatestaticMatCreateSourceImage(){// 用递增数字构造一张简单测试图,便于观察坐标变化。varsource=newMat(5,5,MatType.CV_8UC1);bytevalue=1;for(varrow=0;row<source.Rows;row++){for(varcol=0;col<source.Cols;col++){source.At<byte>(row,col)=value++;}}returnsource;}/// <summary>/// 创建一个手写错切矩阵。/// </summary>/// <returns>2x3 仿射矩阵。</returns>privatestaticMatCreateShearMatrix(){// 这里让 x 和 y 方向都带一点斜切,便于和旋转结果对比。varmatrix=newMat(2,3,MatType.CV_64FC1);matrix.At<double>(0,0)=1.0;matrix.At<double>(0,1)=0.25;matrix.At<double>(0,2)=0.0;matrix.At<double>(1,0)=0.10;matrix.At<double>(1,1)=1.0;matrix.At<double>(1,2)=0.0;returnmatrix;}/// <summary>/// 打印单通道矩阵。/// </summary>privatestaticvoidPrintMat(Matmat){for(varrow=0;row<mat.Rows;row++){for(varcol=0;col<mat.Cols;col++){// 这里统一按 double 读取,便于打印矩阵和图像结果。varvalue=mat.Type()==MatType.CV_64FC1?mat.At<double>(row,col):mat.At<byte>(row,col);Console.Write($"{value,8:F2}");}Console.WriteLine();}Console.WriteLine();}}

8. 注意事项

  1. WarpAffine需要的是 2x3 矩阵,不是 3x3 矩阵。
  2. 如果矩阵里写了平移项,图像会整体移动。
  3. 如果矩阵里写了错切项,图像会倾斜。
  4. 边界模式会影响被变换到源图外侧的像素。

9. 调优建议

  1. 教学时先从GetRotationMatrix2D得到矩阵,再把它交给WarpAffine
  2. 如果你想演示错切,手写 2x3 矩阵比直接调用更直观。
  3. 需要更平滑的结果时,优先尝试INTER_LINEAR
  4. 初学者可以先把dsize设成与源图相同,便于看懂坐标变化。

10. 运行说明

  1. 如果你在控制台工程里运行本文示例,直接把代码放进Program.cs即可。
  2. 如果你在本仓库里学习,请打开 WPF 控件 Cv2WarpAffineControl.xaml.cs 对应的页面。
  3. 点击“运行场景A”,可以同时看到旋转矩阵和错切矩阵的效果。

11. 常见错误排查

  1. 把 3x3 透视矩阵误传给WarpAffine
  2. 只改了矩阵,却没有调用WarpAffine,导致图像没有变化。
  3. 忘记设置合适的边界模式,边缘出现不想要的填充值。
  4. 把仿射变换误认为只能做旋转。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 19:04:41

抖音批量下载神器:高效获取无水印视频的完整指南

抖音批量下载神器&#xff1a;高效获取无水印视频的完整指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖…

作者头像 李华
网站建设 2026/4/21 19:04:39

从A卡到N卡:我的DeepFaceLab踩坑实录与2024年显卡选购避坑指南

从A卡到N卡&#xff1a;我的DeepFaceLab踩坑实录与2024年显卡选购避坑指南 在数字内容创作领域&#xff0c;DeepFaceLab已成为人脸交换技术的标杆工具。作为一名长期使用AMD显卡的创作者&#xff0c;我经历了从RX 6800XT到RTX 4090的完整迁移过程&#xff0c;这段经历让我深刻认…

作者头像 李华
网站建设 2026/4/21 19:00:41

Spring Boot 4.0发布倒计时72小时:Agent-Ready架构终极设计图泄露——你还在用Spring Boot 3.x的字节码方案?

第一章&#xff1a;Spring Boot 4.0 Agent-Ready架构的演进逻辑与战略定位Spring Boot 4.0 将“Agent-Ready”确立为核心架构范式&#xff0c;标志着从被动可观测性向主动智能代理能力的根本跃迁。这一演进并非简单叠加监控探针&#xff0c;而是重构应用生命周期管理的底层契约…

作者头像 李华