勇哥注:
把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
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路


















