勇哥注:
把C#做为Lua的宿主,然后把把halcon算子封装成Lua的功能函数,就可以创建内嵌脚本。
你可以随时修改脚本,然后继续运行程序,实时生效。
或者你也可以指一个命令行窗口,以指令方式去执行封装好的Lua的功能函数,起到调试的效果。
内嵌脚本的好处是可以运行时暂停设备后,修改脚本后可以继续运行,这样不用为了修改功能而关闭软件,再修改软件后重新编译。这样可以非常灵活的在线修改逻辑。
以上的效果类似于Epson机器人的内嵌VB脚本语言,此模式在业内被大量应用。
(一)先写一段C#调用halcon功能的代码
如下,非常简单,只有打开相机、抓照、连续抓拍、停止抓拍 四个动作。
我们计划封装出来的Lua函数也做这个4个动作。
下面是C# 代码:
using HalconDotNet; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { private HTuple ccdHandle = new HTuple(); public Form1() { InitializeComponent(); ccdHandle.Dispose(); } private void button1_Click(object sender, EventArgs e) { HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false", "default", "[0] USB Camera", 0, -1, out ccdHandle); HOperatorSet.GrabImage(out HObject img, ccdHandle); HOperatorSet.GetImageSize(img, out HTuple width, out HTuple height); hWin.HalconWindow.SetPart(new HTuple(0), new HTuple(0), height, width); button1.Enabled = false; button2.Enabled = true; button3.Enabled = true; button4.Enabled = true; } private void button2_Click(object sender, EventArgs e) { HObject img; HOperatorSet.GenEmptyObj(out img); img.Dispose(); HOperatorSet.GrabImage(out img, ccdHandle); hWin.HalconWindow.DispObj(img); img.Dispose(); } private bool QuitGrab = false; private void button3_Click(object sender, EventArgs e) { QuitGrab = false; HObject img; HOperatorSet.GenEmptyObj(out img); img.Dispose(); HOperatorSet.GrabImageStart(ccdHandle, -1); Task.Factory.StartNew(() => { while (!QuitGrab) { HOperatorSet.GrabImageAsync(out img, ccdHandle, -1); hWin.HalconWindow.DispObj(img); img.Dispose(); //(1) Thread.Sleep(5); } img.Dispose(); }); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { HOperatorSet.CloseFramegrabber(ccdHandle); ccdHandle.Dispose(); } private void button4_Click(object sender, EventArgs e) { QuitGrab = true; } private void Form1_Load(object sender, EventArgs e) { button1.Enabled = true; button2.Enabled = false; button3.Enabled = false; button4.Enabled = false; } } }
注:
(1)注意 这句img.Dispose(); 非常重要,在异常连续拍图时,如果没有这句,你的内存会像坐火箭一样向上升。
(2)演示时勇哥用的是VS2017+halcon19.11
(二)改造成Lua内嵌脚本
改造效果如下:
脚本编辑框中,可以以Lua的语法调用下面几个函数:
init() //初始化相机
grab() //拍照
cgrab() //连续拍图
stop() //停止连续拍图
close() //关闭设备
有关Lua语言的介绍及简易语法说明见下面贴子:
Lua语法的代码演示
实时指令那个文本框内,你可以直接敲入上面的函数名(不带括号),回车即可以执行。
源代码:
using HalconDotNet; using NLua; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { private Lua Luas = new Lua(); // lua脚本的地址 private string LuaPath; HalconFun halcon = HalconFun.Instance; public Form1() { InitializeComponent(); halcon.SetHwin(this.hWin); } private void button1_Click(object sender, EventArgs e) { halcon.init(); button1.Enabled = false; button2.Enabled = true; button3.Enabled = true; button4.Enabled = true; } private void button2_Click(object sender, EventArgs e) { halcon.grab(); } private void button3_Click(object sender, EventArgs e) { halcon.cgrab(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { halcon.close(); } private void button4_Click(object sender, EventArgs e) { halcon.stop(); } private void Form1_Load(object sender, EventArgs e) { Luas.State.Encoding = Encoding.UTF8; LoadLua(); button1.Enabled = true; button2.Enabled = false; button3.Enabled = false; button4.Enabled = false; } private void LoadLua() { try { Luas.LoadCLRPackage(); Luas.DoString(richTextBox1.Text); // 注册C#函数供Lua调用 //Luas.RegisterFunction("CSharpFunction", this, typeof(Form1).GetMethod("CSharpFunction")); //lua.RegisterFunction 注册静态方法(注册到Lua中以后方法的名称,空,程序的类型 typeof(Program).(传入C#中的方法名:需要是公有方法)) Luas.RegisterFunction("msgshow", null, typeof(MessageBox).GetMethod("Show", new[] { typeof(string) })); Luas.RegisterFunction("init", halcon, typeof(HalconFun).GetMethod("init")); Luas.RegisterFunction("grab", halcon, typeof(HalconFun).GetMethod("grab")); Luas.RegisterFunction("cgrab", halcon, typeof(HalconFun).GetMethod("cgrab")); Luas.RegisterFunction("stop", halcon, typeof(HalconFun).GetMethod("stop")); Luas.RegisterFunction("close", halcon, typeof(HalconFun).GetMethod("close")); } catch (Exception ex) { Debug.WriteLine(ex.Message); } } private void button5_Click(object sender, EventArgs e) { try { Luas.LoadCLRPackage(); Luas.DoString(richTextBox1.Text); MessageBox.Show("重载成功!"); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void button6_Click(object sender, EventArgs e) { try { Luas.GetFunction("LuaFunction").Call(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void button7_Click(object sender, EventArgs e) { this.textBox1.Text = ""; } private void textBox1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyValue == (char)Keys.Enter)//设置监听键为回车 { switch(this.textBox1.Text) { case "init": halcon.init(); break; case "grab": halcon.grab(); break; case "cgrab": halcon.cgrab(); break; case "stop": halcon.stop(); break; case "close": halcon.close(); break; } } } } public class HalconFun { private static readonly Lazy<HalconFun> lazyInstance = new Lazy<HalconFun>(() => new HalconFun()); public static HalconFun Instance => lazyInstance.Value; private HTuple ccdHandle = new HTuple(); private HWindowControl myHwin; private bool QuitGrab = false; HalconFun() { } public void SetHwin(HWindowControl _win) { this.myHwin = _win; } public void init() { HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false", "default", "[0] USB Camera", 0, -1, out ccdHandle); HOperatorSet.GrabImage(out HObject img, ccdHandle); HOperatorSet.GetImageSize(img, out HTuple width, out HTuple height); myHwin.HalconWindow.SetPart(new HTuple(0), new HTuple(0), height, width); } public void grab() { HObject img; HOperatorSet.GenEmptyObj(out img); img.Dispose(); HOperatorSet.GrabImage(out img, ccdHandle); myHwin.HalconWindow.DispObj(img); img.Dispose(); } public void cgrab() { QuitGrab = false; HObject img; HOperatorSet.GenEmptyObj(out img); img.Dispose(); HOperatorSet.GrabImageStart(ccdHandle, -1); Task.Factory.StartNew(() => { while (!QuitGrab) { HOperatorSet.GrabImageAsync(out img, ccdHandle, -1); myHwin.HalconWindow.DispObj(img); img.Dispose(); Thread.Sleep(5); } img.Dispose(); }); } public void stop() { QuitGrab = true; } public void close() { HOperatorSet.CloseFramegrabber(ccdHandle); ccdHandle.Dispose(); } } }
勇哥注:
init函数里勇哥是halcon方式初始化了手里的一个usb相机。
你可以把它换成你自己的相机,或者改成文件。
可执行的源码下载:
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

