WPF+Halcon 培训项目实战(7):目标匹配助手

前言

为了更好地去学习WPF+Halcon,我决定去报个班学一下。原因无非是想换个工作。相关的教学视频来源于下方的Up主的提供的教程。这里只做笔记分享,想要源码或者教学视频可以和他联系一下。

相关链接

微软系列技术教程 WPF 年度公益课程

Halcon开发 CSDN博客专栏

个人学习的Gitee 项目地址仓库

项目专栏

WPF+Halcon实战项目

运行环境

  • .net core 8.0
  • visual studio 2022
  • halcon HDevelop 20.11
  • windows 11

匹配图片

在这里插入图片描述

7.Halcon代码导出

简单的模板匹配代码

* 读取Resource的文件
read_image (Image, '../resource/1.png')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_display (Image)* 截取ROI
draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
gen_rectangle1 (Rectangle, Row1, Column1, Row2, Column2)
reduce_domain (Image, Rectangle, ImageReduced)* 生成匹配模板
create_shape_model (ImageReduced, 'auto', -0.39, 0.79, 'auto', 'auto', 'use_polarity', 'auto', 'auto', ModelID)
* 导出匹配模板
write_shape_model (ModelID, 'output.sha')find_shape_model (ImageReduced, ModelID, -0.39, 0.79, 0.5, 1, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score)

导出C#代码

在这里插入图片描述
我之前做过C# 代码导出,详情看这个网址

Halcon WPF 开发学习笔记(2):Halcon导出c#脚本和WPF初步开发

控制台测试

这里使用.net core 8.0新建项目

在这里插入图片描述

导入halcon.dll

可以通过安装目录的dll导入程序

在这里插入图片描述
也可以直接在Nuget上面搜索halcon
在这里插入图片描述

using HalconDotNet;namespace ConsoleApp1
{internal class Program{static void Main(string[] args){HObject img;HOperatorSet.GenEmptyObj(out img);//读取图片,这里填你的图片的位置HOperatorSet.ReadImage(out img, "Resources\\1.png");//读取形状匹配模板,路径选择你的文件路径HTuple modelId = new HTuple();HOperatorSet.ReadShapeModel("Resources\\output.shm", out modelId);//匹配Image中的结果HTuple hv_WindowHandle = new HTuple(), hv_Row1 = new HTuple();HTuple hv_Column1 = new HTuple(), hv_Row2 = new HTuple();HTuple hv_Column2 = new HTuple(), hv_ModelID = new HTuple();HTuple hv_Row = new HTuple(), hv_Column = new HTuple();HTuple hv_Angle = new HTuple(), hv_Score = new HTuple();//hv_Row.Dispose(); hv_Column.Dispose(); hv_Angle.Dispose(); hv_Score.Dispose();HOperatorSet.FindShapeModel(img, modelId, -0.39, 0.79, 0.5, 1,0.5, "least_squares", 0, 0.9, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);//输出匹配结果Console.WriteLine($"分数:{hv_Score},Row坐标:{hv_Row},Col坐标:{hv_Column},角度:{hv_Angle}");Console.WriteLine("程序运行完毕!");Console.ReadKey();}}
}

运行报错:

在这里插入图片描述
在这里插入图片描述

运行结果:

在这里插入图片描述

7.WPF导入Halcon

如果你上个代码已经跑成功了,说明你已经能成功导入Halcon代码并进行运行,接下来我们就要开始学习WPF如何导入Halcon

新建WPF程序

我不想使用Prism框架,我想用HandyControl替换Material Design UI框架。所以我前端时间尝试了一下代码的书写。

将程序修改为控制台程序
在这里插入图片描述

WPF仿网易云搭建笔记(7):HandyControl重构

Halcon WPF 开发学习笔记(3):WPF+Halcon初步开发

WPF 消息日志打印帮助类:HandyControl+NLog+彩色控制台打印+全局异常捕捉

WPF-UI HandyControl 控件简单实战+IconPacks矢量图导入

由于WPF比较复杂,这里我就不展开说明了。具体代码可以看我的Gitee仓库

个人学习的Gitee 项目地址仓库

Nuget目录

在这里插入图片描述

项目目录

在这里插入图片描述

相关代码

app.xaml:导入HandyControl Style主题

<Application x:Class="WpfApp1.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:WpfApp1"StartupUri="MainWindow.xaml"><Application.Resources><ResourceDictionary><!--导入HandyControl Style主题--><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" /><ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" /></ResourceDictionary.MergedDictionaries></ResourceDictionary></Application.Resources>
</Application>

App.xaml.cs:全局异常捕捉

using System.Configuration;
using System.Data;
using System.Text;
using System.Windows;
using System.Windows.Threading;
using WpfApp1.Utils;namespace WpfApp1
{/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : Application{public App(){//首先注册开始和退出事件this.Startup += new StartupEventHandler(App_Startup);this.Exit += new ExitEventHandler(App_Exit);}void App_Startup(object sender, StartupEventArgs e){//UI线程未捕获异常处理事件this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);//Task线程内未捕获异常处理事件TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;//非UI线程未捕获异常处理事件AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);}void App_Exit(object sender, ExitEventArgs e){//程序退出时需要处理的业务}void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e){try{e.Handled = true; //把 Handled 属性设为true,表示此异常已处理,程序可以继续运行,不会强制退出      MsgHelper.Error("UI线程异常:" + e.Exception.Message);//MessageBox.Show("UI线程异常:" + e.Exception.Message);}catch (Exception ex){//此时程序出现严重异常,将强制结束退出//MessageBox.Show("UI线程发生致命错误!");MsgHelper.FatalGlobal("UI线程发生致命错误!"+ex.ToString());}}void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e){StringBuilder sbEx = new StringBuilder();if (e.IsTerminating){sbEx.Append("非UI线程发生致命错误");}sbEx.Append("非UI线程异常:");if (e.ExceptionObject is Exception){sbEx.Append(((Exception)e.ExceptionObject).Message);}else{sbEx.Append(e.ExceptionObject);}//MessageBox.Show(sbEx.ToString());MsgHelper.Error(sbEx.ToString());}void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e){//task线程内未处理捕获MsgHelper.Error("Task线程异常:" + e.Exception.Message);//MessageBox.Show("Task线程异常:" + e.Exception.Message);e.SetObserved();//设置该异常已察觉(这样处理后就不会引起程序崩溃)}}}

NlogHelper:日志打印

using NLog.Config;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp1.Utils
{public static class NLogHelper{private static Logger logger;static NLogHelper(){LogManager.Configuration = new XmlLoggingConfiguration(string.Format("{0}/NLog.config", AppDomain.CurrentDomain.BaseDirectory.ToString()));logger = NLog.LogManager.GetCurrentClassLogger();}public static void Debug(string msg){Console.WriteLine(msg);logger.Debug(msg);}public static void Info(string msg){ConsoleWirte(msg,ConsoleColor.Green);logger.Info(msg);}public static void Error(string msg){ConsoleWirte(msg, ConsoleColor.Red);logger.Error(msg);}public static void Warning(string msg){ConsoleWirte(msg, ConsoleColor.Yellow);logger.Warn(msg);}public static void ConsoleWirte(string msg,ConsoleColor color){Console.ForegroundColor = color;Console.WriteLine(msg);Console.ResetColor();}}
}

MsgHelper:HandyControl+NLog组合

using HandyControl.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace WpfApp1.Utils
{public static class MsgHelper{public enum MsgType { Info, Warn, Error, Success, Fatal }/// <summary>/// 打印消息/// </summary>/// <param name="msg"></param>/// <param name="type"></param>/// <param name="isGlobal"></param>public static void ShowMsg(string msg, MsgType type, bool isGlobal = false){if (isGlobal){switch (type){case MsgType.Info:NLogHelper.Info(msg);Growl.InfoGlobal(msg);break;case MsgType.Warn:NLogHelper.Warning(msg);Growl.WarningGlobal(msg);break;case MsgType.Error:NLogHelper.Error(msg);Growl.ErrorGlobal(msg);break;case MsgType.Success:NLogHelper.Info(msg);Growl.SuccessGlobal(msg);break;case MsgType.Fatal:NLogHelper.Error(msg);Growl.FatalGlobal(msg);break;}}else{switch (type){case MsgType.Info:NLogHelper.Info(msg);Growl.Info(msg);break;case MsgType.Warn:NLogHelper.Warning(msg);Growl.Warning(msg);break;case MsgType.Error:NLogHelper.Error(msg);Growl.Error(msg);break;case MsgType.Success:NLogHelper.Info(msg);Growl.Success(msg);break;case MsgType.Fatal:NLogHelper.Error(msg);Growl.Fatal(msg);break;}}}/// <summary>/// 询问回调/// </summary>/// <param name="msg"></param>/// <param name="callback"></param>/// <param name="isGlobal"></param>public static void Ask(string msg, Action<bool> callback, bool isGlobal = false){NLogHelper.Info(msg);if (isGlobal){Growl.AskGlobal(msg, isConfrimed =>{callback(isConfrimed);return true;});}else{Growl.Ask(msg, isConfrimed =>{callback(isConfrimed);return true;});}}/// <summary>/// 强制清空全部消息/// </summary>public static void CleanAll(){Growl.Clear();Growl.ClearGlobal();}public static void Info(string msg){NLogHelper.Info(msg);Growl.Info(msg);}public static void Warning(string msg){NLogHelper.Warning(msg);Growl.Warning(msg);}public static void Error(string msg) {NLogHelper.Error(msg);Growl.Error(msg);}public static void Fatal(string msg) {NLogHelper.Error(msg);Growl.Fatal(msg);}public static void Success(string msg) {NLogHelper.Info(msg);Growl.Success(msg);}public static void InfoGlobal(string msg){NLogHelper.Info(msg);Growl.InfoGlobal(msg);}public static void WarningGlobal(string msg){NLogHelper.Warning(msg);Growl.WarningGlobal(msg);}public static void ErrorGlobal(string msg){NLogHelper.Error(msg);Growl.ErrorGlobal(msg);}public static void FatalGlobal(string msg){NLogHelper.Error(msg);Growl.FatalGlobal(msg);}public static void SuccessGlobal(string msg){NLogHelper.Info(msg);Growl.SuccessGlobal(msg);}}
}

IconPacksExtesion:IconPacks Material Design 矢量Icon扩展

using MahApps.Metro.IconPacks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
using System.Windows.Media;namespace WpfApp1.ViewModels
{public class IconPacksExtesion : PackIconGeometryExtension<PackIconMaterialKind>{protected override IDictionary<PackIconMaterialKind, string> DataIndex => PackIconMaterialDataFactory.DataIndex.Value;public IconPacksExtesion() { }public IconPacksExtesion(PackIconMaterialKind kind) : base(kind) { }}public abstract class PackIconGeometryExtension<TKind> : MarkupExtension where TKind : Enum{public TKind Kind { get; set; }protected abstract IDictionary<TKind, string> DataIndex { get; }protected PackIconGeometryExtension() { }protected PackIconGeometryExtension(TKind kind) => Kind = kind;public override object ProvideValue(IServiceProvider serviceProvider) => Geometry.Parse(DataIndex[Kind]);}
}

注意:这里已经默认你很了解WPF程序项目。已经搭建好了WPF框架。而且本项目不会使用Prism,而是使用原生的WPF MVVM开发

程序生成时将整个Resources文件复制到Debug文件夹中

Visual Studio C# 项目生成时复制项目资源目录到生成目录
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

初始界面测试

MainView

<Window x:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp1"xmlns:Views="clr-namespace:WpfApp1.Views"xmlns:ViewModels="clr-namespace:WpfApp1.ViewModels"xmlns:hc="https://handyorg.github.io/handycontrol"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><Window.DataContext><ViewModels:MainViewModel /></Window.DataContext><Grid><hc:TabControl Style="{StaticResource TabControlInLine}"><hc:TabItem Header="Halcon测试界面"><Views:HalconView /></hc:TabItem><!--存放你其它的页面--></hc:TabControl></Grid>
</Window>

HalconView.xaml

<UserControl x:Class="WpfApp1.Views.HalconView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="clr-namespace:WpfApp1.Views"mc:Ignorable="d"xmlns:ViewModels="clr-namespace:WpfApp1.ViewModels"xmlns:hc="https://handyorg.github.io/handycontrol"xmlns:halcon="clr-namespace:HalconDotNet;assembly=halcondotnet"d:DesignHeight="450"d:DesignWidth="800"><UserControl.DataContext><ViewModels:HalconViewModel /></UserControl.DataContext><UserControl.Resources><Style TargetType="Button"x:Key="MyButton"BasedOn="{StaticResource {x:Type Button}}"><Setter Property="Margin"Value="5" /></Style></UserControl.Resources><DockPanel><StackPanel Orientation="Horizontal"DockPanel.Dock="Top"><StackPanel.Resources><Style TargetType="Button"BasedOn="{StaticResource MyButton}" /></StackPanel.Resources><Button Content="读取图片"hc:IconElement.Geometry="{ViewModels:IconPacksExtesion Kind=ImagePlus}" Command="{Binding ReadImgBtn}" /><Button Content="定位结果"hc:IconElement.Geometry="{ViewModels:IconPacksExtesion Kind=ImageMarkerOutline}" Command="{Binding LocateBtn}"/><Button Content="生成矩形"hc:IconElement.Geometry="{ViewModels:IconPacksExtesion Kind=ShapeRectanglePlus}" Command="{Binding InitRectangleBtn}"/><Button Content="生成图片"hc:IconElement.Geometry="{ViewModels:IconPacksExtesion Kind=StickerPlus}" Command="{Binding InitImgBtn}"/></StackPanel><halcon:HSmartWindowControlWPF /></DockPanel>
</UserControl>

HalconViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfApp1.Utils;namespace WpfApp1.ViewModels
{public class HalconViewModel : ObservableObject{public RelayCommand ReadImgBtn { get; set; }public RelayCommand LocateBtn {  get; set; }public RelayCommand InitRectangleBtn { get; set; }public RelayCommand InitImgBtn { get; set; }public HalconViewModel() {ReadImgBtn = new RelayCommand(() =>{MsgHelper.Info("读取图片");});LocateBtn = new RelayCommand(() => {MsgHelper.Info("显示定位结果");});InitRectangleBtn = new RelayCommand(() => {MsgHelper.Info("生成矩形");});InitImgBtn = new RelayCommand(() => {MsgHelper.Info("生成图片");});}}
}

测试运行结果

在这里插入图片描述

总结

下一章我们将重点转移到WPF 的Halcon组件的使用中去。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows定时重启Tomcat

项目场景&#xff1a; 系统&#xff1a;Windows 7 Tomcat&#xff1a;apache-tomcat-8.0.5 JDK&#xff1a;1.8 问题描述 最近项目的Tomcat隔一段时间就假死&#xff0c;最后想到的解决方式就是&#xff1a;每天凌晨1点重启tomact。 解决方案&#xff1a; 使用Windows系统…

飞企互联-FE企业运营管理平台 登录绕过漏洞复现

0x01 产品简介 飞企互联-FE企业运营管理平台是一个基于云计算、智能化、大数据、物联网、移动互联网等技术支撑的云工作台。这个平台可以连接人、链接端、联通内外&#xff0c;支持企业B2B、C2B与O2O等核心需求&#xff0c;为不同行业客户的互联网转型提供支持。 0x02 漏洞概…

系列四、Eureka自我保护

一、Eureka自我保护 1.1、故障现象 保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式&#xff0c;Eureka Server将会尝试保护其服务注册表中的信息&#xff0c;不再删除服务注册表中的数据&#xff0c;也就是不会注销任何微服务。如…

TCP 协议为什么要设计三次握手 TCP 协议,是一种可靠的,基于字节流的,面向连接的传输层协议。

文章目录 TCP 协议为什么要设计三次握手TCP 协议&#xff0c;是一种可靠的&#xff0c;基于字节流的&#xff0c;面向连接的传输层协议。TCP 通信双方的数据传输是通过字节流来实现传输的客户端向服务端发送连接请求并携带同步序列号 SYN。 今天我们来谈谈tcp的三次握手 TCP 协…

基于yolov2深度学习网络的血细胞检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1YOLOv2算法原理 4.2 YOLOv2网络结构 4.3 血细胞检测算法实现 数据集准备 数据预处理 网络训练 模型评估与优化 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MAT…

特征归一化及其原理--机器学习

归一化是数据预处理中的一种常见操作&#xff0c;其目的是将不同特征的数值范围统一或缩放到相似的尺度。这有助于提高模型的性能&#xff0c;加速模型的收敛&#xff0c;并使模型更加稳健。以下是进行归一化的一些原因和原理&#xff1a; 消除特征间的尺度差异&#xff1a; 不…

一招搞定msvcr100.dll缺失问题,msvcr100.dll丢失的多种解决方法

msvcr100.dll是Microsoft Visual C 2010 Redistributable Package的一部分&#xff0c;它是运行许多基于Windows操作系统上的应用程序所必需的动态链接库文件。如果该文件安装不正确、丢失或损坏&#xff0c;则使用该文件的应用程序将无法正常启动&#xff0c;会出现“无法启动…

数据库开发之事务和索引的详细解析

2. 事务 场景&#xff1a;学工部整个部门解散了&#xff0c;该部门及部门下的员工都需要删除了。 操作&#xff1a; -- 删除学工部 delete from dept where id 1; -- 删除成功 ​ -- 删除学工部的员工 delete from emp where dept_id 1; -- 删除失败&#xff08;操作过程中…

微信小程序开发系列-07组件

在开发小程序的过程中会遇到一个常见的问题&#xff0c;怎样将其他同事提供的样式或者第三方的样式载入自己的工程&#xff0c;本文基于这个问题为索引&#xff0c;探索下小程序的组件。 什么是组件 组件是视图层的基本组成单元。组件自带一些功能与微信风格一致的样式。一个…

统一入口,全面提升工作效率,WorkPlus超级APP引领数字化办公新潮流

在数字化办公的时代&#xff0c;企业往往面临着多个应用管理的挑战。员工需要在众多应用之间切换&#xff0c;记忆不同的登录凭证&#xff0c;这不仅分散了注意力&#xff0c;还降低了工作效率。为了应对这一问题&#xff0c;企业需要一站式的解决方案&#xff0c;通过整合繁杂…

SAP缓存 表缓存( Table Buffering)

本文主要介绍SAP中的表缓存在查询数据&#xff0c;更新数据时的工作情况以及对应概念。 SAP表缓存的工作 查询数据 更新数据 删除数据 表缓存的概念 表缓存技术设置属性 不允许缓冲&#xff1a; 允许缓冲&#xff0c;但已关闭&#xff1a; 缓冲已激活&#xff1a; 已…

qt连接hiki相机进行拍照保存

.pro QT工程pro文件模板变量&#xff08;TEMPLATE&#xff09;模板变量告诉qmake为这个应用程序生成哪种makefile。下面是可供使用的选择&#xff1a; app - 建立一个应用程序的makefile。这是默认值&#xff0c;所以如果模板没有被指定&#xff0c;这个将被使用。 lib - …