前端界面
1首先定义一个全局的halcon窗体
//先定义一个Windows的窗口并实例化他
private HTuple windownID = new HTuple();
2然后配置hWindowControl1和halcon中的窗体映射关系,并随控件大小全屏显示。
//打开一个halcon窗体。将windownID映射到hWindowControl1.HalconWindow
HOperatorSet.OpenWindow(0, 0, this.hWindowControl1.Width, this.hWindowControl1.Height, hWindowControl1.HalconWindow, "visible", "", out windownID);
//将窗体与WPF中halcon控件绑定否则无法显示图片黑屏
HDevWindowStack.Push(windownID);
//将相机的像素设置到窗体。否则无法显示齐全。
HOperatorSet.SetPart(windownID, 0, 0, 720, 1280);
//调用显示函数显示图片
HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
3然后直接将halcon代码导出复制到代码中直接使用,完整代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using HalconDotNet;
using System.Threading;
namespace WPF
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
//先定义一个Windows的窗口并实例化他
private HTuple windownID = new HTuple();
public MainWindow()
{
InitializeComponent();
}
int y;
public void kais()
{
int x=0;
//先关闭相机,否则打开后相机,再次打开时候会报相机初始化错误。
HOperatorSet.CloseAllFramegrabbers();
//打开一个halcon窗体。将windownID映射到hWindowControl1.HalconWindow
HOperatorSet.OpenWindow(0, 0, this.hWindowControl1.Width, this.hWindowControl1.Height, hWindowControl1.HalconWindow, "visible", "", out windownID);
//将窗体与WPF中halcon控件绑定否则无法显示图片黑屏
HDevWindowStack.Push(windownID);
//将相机的像素设置到窗体。否则无法显示齐全。
HOperatorSet.SetPart(windownID, 0, 0, 720, 1280);
//调用显示函数显示图片
HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
HObject ho_Image, ho_ModelRegion, ho_TemplateImage;
HObject ho_ModelContours, ho_TransContours, ho_Image1 = null;
// Local control variables
HTuple hv_AcqHandle = null, hv_ModelID = null;
HTuple hv_ModelRegionArea = null, hv_RefRow = null, hv_RefColumn = null;
HTuple hv_HomMat2D = null, hv_ResultHomMat2D = new HTuple();
HTuple hv_Score = new HTuple(), hv_I = new HTuple(), hv_TempHomMat2D = new HTuple();
// Initialize local and output iconic variables
HOperatorSet.GenEmptyObj(out ho_Image);
HOperatorSet.GenEmptyObj(out ho_ModelRegion);
HOperatorSet.GenEmptyObj(out ho_TemplateImage);
HOperatorSet.GenEmptyObj(out ho_ModelContours);
HOperatorSet.GenEmptyObj(out ho_TransContours);
HOperatorSet.GenEmptyObj(out ho_Image1);
//
//Matching 01: ************************************************
//Matching 01: BEGIN of generated code for model initialization
//Matching 01: ************************************************
//
//Matching 01: Initialize acquisition
HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb",
-1, "false", "default", "[1] Integrated Webcam", 0, -1, out hv_AcqHandle);
//
//Matching 01: Obtain the model image
ho_Image.Dispose();
HOperatorSet.ReadImage(out ho_Image, "C:/Users/Administrator/Desktop/57134ec9272d19880c479c456e09d08.png");
//
//Matching 01: Build the ROI from basic regions
ho_ModelRegion.Dispose();
HOperatorSet.GenRectangle1(out ho_ModelRegion, 207.874, 742.5, 347.274, 816.5);
//
//Matching 01: Reduce the model template
ho_TemplateImage.Dispose();
HOperatorSet.ReduceDomain(ho_Image, ho_ModelRegion, out ho_TemplateImage);
//
//Matching 01: Create the deformable model
HOperatorSet.CreatePlanarUncalibDeformableModel(ho_TemplateImage, 4, (new HTuple(0)).TupleRad()
, (new HTuple(360)).TupleRad(), (new HTuple(1)).TupleRad(), 1, 1, 0.02, 1,
1, 0.02, "none", "use_polarity", (new HTuple(42)).TupleConcat(55), 10, new HTuple(),
new HTuple(), out hv_ModelID);
//
//Matching 01: Get the model contour for transforming it later into the image
ho_ModelContours.Dispose();
HOperatorSet.GetDeformableModelContours(out ho_ModelContours, hv_ModelID, 1);
//
//Matching 01: Get the reference position
HOperatorSet.AreaCenter(ho_ModelRegion, out hv_ModelRegionArea, out hv_RefRow,
out hv_RefColumn);
HOperatorSet.VectorAngleToRigid(0, 0, 0, hv_RefRow, hv_RefColumn, 0, out hv_HomMat2D);
ho_TransContours.Dispose();
HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_TransContours, hv_HomMat2D);
//
//Matching 01: Display the model contours
if (HDevWindowStack.IsOpen())
{
HOperatorSet.SetColor(HDevWindowStack.GetActive(), "green");
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.SetDraw(HDevWindowStack.GetActive(), "margin");
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_ModelRegion, HDevWindowStack.GetActive());
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_TransContours, HDevWindowStack.GetActive());
}
// stop(...); only in hdevelop
//
//Matching 01: END of generated code for model initialization
//Matching 01: * * * * * * * * * * * * * * * * * * * * * * *
//Matching 01: BEGIN of generated code for model application
//
while ((int)(1) != 0)
{
//
//Matching 01: Obtain the image
ho_Image.Dispose();
HOperatorSet.GrabImage(out ho_Image, hv_AcqHandle);
//
//Matching 01: Find the model
HOperatorSet.FindPlanarUncalibDeformableModel(ho_Image, hv_ModelID, (new HTuple(0)).TupleRad()
, (new HTuple(360)).TupleRad(), 1, 1, 1, 1, 0.5, 0, 0.5, 4, 0.75, "subpixel",
"least_squares_very_high", out hv_ResultHomMat2D, out hv_Score);
//
//Matching 01: Transform the model contours into the detected positions
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
}
for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Score.TupleLength())) - 1); hv_I = (int)hv_I + 1)
{
hv_TempHomMat2D = hv_ResultHomMat2D.TupleSelectRange(hv_I * 9, (hv_I * 9) + 8);
ho_TransContours.Dispose();
HOperatorSet.ProjectiveTransContourXld(ho_ModelContours, out ho_TransContours,
hv_TempHomMat2D);
if (HDevWindowStack.IsOpen())
{
HOperatorSet.SetColor(HDevWindowStack.GetActive(), "green");
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_TransContours, HDevWindowStack.GetActive());
}
ho_Image1.Dispose();
// stop(...); only in hdevelop
}
y= hv_Score.Length;
if (y != x)
{
//跨线程更新UI界面
Application.Current.Dispatcher.Invoke(() => {
// UI线程上执行的代码
kk.Items.Add("当前检测到纸数:" + y);
});
x = y;
}
Thread.Sleep(1500);
}
}
}
}
最终实现纸巾数量识别效果
其中WPF跨线程访问控件思考了一下,觉得挺难的,不知道大家有没有什么好的方法。
//跨线程更新UI界面
Application.Current.Dispatcher.Invoke(() => {
// UI线程上执行的代码
kk.Items.Add("当前检测到纸数:" + y);
});
本文作者能力有限,欢迎大家指正批评。