OpencvSharp 算子学习教案之 - Cv2.SetWindowProperty
OpencvSharp 算子学习教案之 - Cv2.SetWindowProperty
大家好,Opencv在很多工程项目中都会用到,而OpencvSharp则是以C#开发与实现的Opencv操作库,对.NET开发人员友好,但很多API的中文资料、应用场景及常见坑点等缺乏系统性归纳,因此这系列博客将给大家带来Cv2及Mat对象全系列算子学习教案,供大家参考学习。
Cv2.SetWindowProperty
- 教案版本:V1.0
- 面向对象:OpenCvSharp 初学者
- 所属模块:highgui
- 源码位置:OpenCvSharp/Cv2/Cv2_highgui.cs:149
摘要:SetWindowProperty 用来动态修改窗口属性,例如置顶、全屏、自动尺寸等。本文选取 Topmost 作为教学属性,演示如何先读取属性、再修改属性、最后恢复属性,帮助初学者理解窗口行为的动态调整方式。
1. 函数名称(带参数签名)
publicstaticvoidSetWindowProperty(stringwinName,WindowPropertyFlagspropId,doublepropValue)2. 函数用途
Cv2.SetWindowProperty的作用,是动态修改指定窗口的属性。
它最常见的用途有:
- 切换窗口是否置顶。
- 切换窗口是否自动尺寸。
- 切换窗口是否全屏。
- 在调试时动态观察窗口行为变化。
这个函数的关键点是:它修改的是窗口属性,不是窗口内容。
3. 函数公式
这个函数更适合用流程图理解,而不是严格的数学公式:
窗口属性旧值→SetWindowProperty(propId,propValue)→窗口属性新值 \text{窗口属性旧值} \rightarrow \text{SetWindowProperty}(propId, propValue) \rightarrow \text{窗口属性新值}窗口属性旧值→SetWindowProperty(propId,propValue)→窗口属性新值
也就是说,SetWindowProperty会把某个窗口属性切换到你指定的新状态。
4. 函数原理说明
这个函数的逻辑可以理解为:
- 接收窗口名称
winName。 - 接收属性编号
propId。 - 接收新的属性值
propValue。 - 把这个属性写回到高 GUI 后端。
对于初学者来说,propId决定你修改什么,propValue决定你把它改成什么。
5. 参数含义解析
| 项目 | 类型 | 含义 |
|---|---|---|
winName | string | 要修改属性的窗口名称 |
propId | WindowPropertyFlags | 要修改的窗口属性编号 |
propValue | double | 新属性值,通常是 0.0 或 1.0 |
| 返回值 | void | 没有返回值,只负责设置属性 |
补充说明:
propId是枚举值,不是字符串。propValue虽然是double,但很多属性只用 0.0/1.0 这种开关值。- 不同后端对某些属性的支持程度可能略有差异。
6. 应用场景列表
| 场景名 | 场景说明 | 典型用途 |
|---|---|---|
| 场景A:切换 Topmost | 把窗口置顶并恢复 | 基础教学 |
| 场景B:切换全屏 | 调整窗口全屏状态 | 交互演示 |
| 场景C:切换自动尺寸 | 控制窗口是否按图像自动缩放 | 窗口布局 |
| 场景D:调试窗口状态 | 动态观察窗口属性变化 | 调试排查 |
7. 函数使用示例
下面的 Console 程序演示Cv2.SetWindowProperty。示例会先读取窗口的 Topmost 属性,再把它设为 1.0,最后恢复回 0.0。
usingSystem.Globalization;usingSystem.Text;usingOpenCvSharp;internalstaticclassProgram{/// <summary>/// 程序入口。/// </summary>privatestaticvoidMain(){// 中文控制台输出使用 UTF-8,避免教学说明乱码。Console.OutputEncoding=Encoding.UTF8;// 调用演示函数,观察窗口属性如何被动态修改。RunSetWindowPropertyDemo();}/// <summary>/// 演示 SetWindowProperty 的完整流程。/// </summary>privatestaticvoidRunSetWindowPropertyDemo(){conststringwindowName="Cv2.SetWindowProperty.Sample";// 准备一张教学图片,让窗口里有内容可以观察。usingvarimage=CreateDemoImage("SetWindowProperty","切换窗口属性 Topmost");// 先清理旧窗口,避免重复运行时残留上一次的状态。TryDestroyWindow(windowName);// 先创建普通窗口并显示图像,然后读取和修改窗口属性。Cv2.NamedWindow(windowName,WindowFlags.Normal);Cv2.ImShow(windowName,image);Cv2.WaitKey(1);// 先读取一次属性值,方便和后续设置结果做对比。varbeforeValue=Cv2.GetWindowProperty(windowName,WindowPropertyFlags.Topmost);// 把窗口置顶,演示 SetWindowProperty 的核心作用。Cv2.SetWindowProperty(windowName,WindowPropertyFlags.Topmost,1.0);Cv2.WaitKey(1);// 再读取一次属性值,观察设置之后的变化。varenabledValue=Cv2.GetWindowProperty(windowName,WindowPropertyFlags.Topmost);// 为了不让示例结束后留下一个“总在最前面”的窗口,这里再把属性恢复回去。Cv2.SetWindowProperty(windowName,WindowPropertyFlags.Topmost,0.0);Cv2.WaitKey(1);// 最后再读一次,确认属性已经恢复。varrestoredValue=Cv2.GetWindowProperty(windowName,WindowPropertyFlags.Topmost);// 教学演示结束后关闭窗口,避免残留。TryDestroyWindow(windowName);Console.WriteLine($"设置前属性值:{beforeValue.ToString(CultureInfo.InvariantCulture)}");Console.WriteLine($"设置为 1.0 后:{enabledValue.ToString(CultureInfo.InvariantCulture)}");Console.WriteLine($"恢复为 0.0 后:{restoredValue.ToString(CultureInfo.InvariantCulture)}");}/// <summary>/// 创建用于演示的教学图片。/// </summary>/// <param name="title">主标题。</param>/// <param name="subtitle">副标题。</param>/// <returns>彩色教学图。</returns>privatestaticMatCreateDemoImage(stringtitle,stringsubtitle){// 先创建一张浅色背景图,方便后续文字和图形清楚显示。varcanvas=newMat(360,520,MatType.CV_8UC3,newScalar(246,243,238));// 画边框和标题,让这张图更像教学素材。Cv2.Rectangle(canvas,newRect(18,18,484,324),newScalar(66,84,118),3,LineTypes.AntiAlias);Cv2.PutText(canvas,title,newPoint(44,84),HersheyFonts.HersheySimplex,1.0,newScalar(58,48,44),2,LineTypes.AntiAlias);Cv2.PutText(canvas,subtitle,newPoint(44,126),HersheyFonts.HersheySimplex,0.8,newScalar(58,48,44),2,LineTypes.AntiAlias);// 再加几个图形,让窗口里的内容更丰富一些。Cv2.Circle(canvas,newPoint(140,214),44,newScalar(80,170,255),-1,LineTypes.AntiAlias);Cv2.Circle(canvas,newPoint(260,214),44,newScalar(120,225,110),-1,LineTypes.AntiAlias);Cv2.Circle(canvas,newPoint(380,214),44,newScalar(50,140,255),-1,LineTypes.AntiAlias);returncanvas;}/// <summary>/// 尝试关闭指定窗口。/// </summary>/// <param name="windowName">窗口名称。</param>privatestaticvoidTryDestroyWindow(stringwindowName){try{// 如果窗口不存在,这里可能会抛异常,所以用 try/catch 做保护。Cv2.DestroyWindow(windowName);}catch{// 清理失败不影响教学示例主体流程。}}}8. 注意事项
propId是窗口属性编号,不是字符串。propValue是double,但很多属性只用 0.0/1.0 这样的开关值。- 不同平台对某些窗口属性的支持程度可能不同。
- 示例结束时最好把属性恢复回去,避免影响后续调试。
9. 调优建议
- 讲解时优先选择 Topmost 这种容易观察的属性。
- 如果你已经拿到
GetWindowProperty的值,先读后改会更容易理解变化。 - 在多窗口演示中,属性切换可以帮助你更好地观察前后层级。
- 建议先把一个属性讲透,再扩展到全屏、自动尺寸等其它属性。
10. 运行说明
- 如果你在控制台工程里运行本文示例,直接把代码放进
Program.cs即可。 - 如果你在本仓库里学习,请打开 WPF 控件
Cv2SetWindowProperty,点击按钮观察属性变化。 - WPF 示例会把属性值变化写入结果文本框。
11. 常见错误排查
- 把
SetWindowProperty当成改图像内容的函数。 - 把
propValue当成整数随意传,忽略它实际是double。 - 改完属性后忘记恢复,导致后面的窗口一直置顶。
- 在不支持该属性的后端上测试,结果和预期不一致。
