勇哥注:
1。 应用MEF后,主窗体程序只使用Interface,不使用Service,很好的解耦。
2。 halcon的功能被分为两部分,一是IHalconWin,它处理halcon窗体的功能
二是IHalconFun,它处理halcon算子部分
不过目前它们没写什么功能,主要功能在两个扩展函数里面。
3。 halcon窗体控件和HObject两个对象,各封装了对应的扩展方法(放在Halcon19.Services.Extends),
使用了链式编程方式。

form的代码:
using halcon19.Interface;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition.Hosting;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static halcon19.DataStruct.HalDataStruct;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
CompositionContainer container = null;
AggregateCatalog catelog = new AggregateCatalog();
//HalconWin win1 = new HalconWin(new HalconDotNet.HWindowControl());
//HalconFun halconApi = new HalconFun();
public Form1()
{
InitializeComponent();
container = new CompositionContainer(new DirectoryCatalog($"{AppDomain.CurrentDomain.BaseDirectory}"));
}
private void button1_Click(object sender, EventArgs e)
{
Lazy<IHalconWin> ta = container.GetExport<IHalconWin>();
IHalconWin win1 = ta.Value;
win1.SetHwindowControl(new HalconDotNet.HWindowControl());
Lazy<IHalconFun> tb = container.GetExport<IHalconFun>();
IHalconFun halconApi = tb.Value;
var hwin = win1.GetHwin();
hwin.Dock = DockStyle.Fill;
groupBox1.Controls.Add(hwin);
int height, width;
string imgpath = "printer_chip_01.png";
hwin.GetImgSize(imgpath, out height, out width)
.SetDraw(SetDarwEnum.margin.ToString())
.SetPart(0, 0, height, width)
.DispObj
(
halconApi.read_image(imgpath)
.thread(150, 255)
.connect()
.shape_connect(
SelectShapeFeatursEnum.area.ToString(),
SelectShapeOperationEnum.and.ToString(),
15000, 99999)
);
}
}
}接口:
public interface IHalconWin
{
HWindowControl GetHwin();
void SetHwindowControl(HWindowControl _myHwin);
}
public interface IHalconFun
{
HObject read_image(string imgPath);
}服务:
[Export(typeof(IHalconFun))]
public class HalconFun: IHalconFun
{
public HObject read_image(string imgPath)
{
HOperatorSet.ReadImage(out HObject img, imgPath);
return img;
}
}注意HalconWin实现类的构造函数不能传参的,否则框架报一个错误。
好像是企图di注入,这个地方让勇哥比较困惑,我也没有标记di注入呀?
所以这里勇哥弄了一个SetHwindowControl函数,调用者手动注入halcon控件。
[Export(typeof(IHalconWin))]
public class HalconWin: IHalconWin
{
private HWindowControl myHwin;
public HalconWin()
{
}
public void SetHwindowControl(HWindowControl _myHwin)
{
this.myHwin = _myHwin;
}
public HWindowControl GetHwin()
{
return myHwin;
}
}扩展函数:
注意:扩展函数和main项目的命名空间要保持一致,否则无法得到vs编辑器端的好处。这是一点遗憾。
扩展函数用来支持链式编程。下面是halcon里的HObject对象的扩展函数。
由于每一个函数都返回HObject,所以就实现了基于HObject对象的链式编程。
public static class HalconFunExctends
{
public static HObject thread(this HObject img, int min, int max)
{
HOperatorSet.Threshold(img, out HObject region, min, max);
return region;
}
public static HObject connect(this HObject region)
{
HOperatorSet.Connection(region, out HObject connectregion);
return connectregion;
}
public static HObject shape_connect(this HObject region, string features, string operation, int min, int max)
{
HOperatorSet.SelectShape(region, out HObject selectRegion, features, operation, min, max);
return selectRegion;
}
}下面是halcon窗体类型HWindowControl的扩展函数。
它设计成任何函数都返回HWindowControl,这样就可以支持链式编程。
public static class HalconWinExtends
{
public static HWindowControl SetPart(this HWindowControl win, int x1, int y1, int y2, int x2)
{
win.HalconWindow.SetPart(x1, y1, y2, x2);
return win;
}
public static HWindowControl SetDraw(this HWindowControl win, string drawtype)
{
win.HalconWindow.SetDraw(drawtype);
return win;
}
public static HWindowControl DispObj(this HWindowControl win, HObject obj)
{
win.HalconWindow.DispObj(obj);
return win;
}
public static HWindowControl GetImgSize(this HWindowControl win, string imgPath, out int _height, out int _width)
{
HOperatorSet.ReadImage(out HObject img, imgPath);
HOperatorSet.GetImagePointer1(img, out HTuple pointer, out HTuple imgtype, out HTuple width, out HTuple height);
_height = height;
_width = width;
return win;
}
}工程结构 :

程序运行的速度也许是大家关心的。MEF的这种动态调用dll,一定是通过反射实现的。
勇哥的电脑上测试结果是:
我们点击run按钮,第一次调用约280ms, 第二次开始是20ms,这个时间估计就只是halcon的算子调用的总时间了。
性能损失是避免不了的。
上面程序比较简单,以后如果有复杂一些的调用时再继续研究一下这个问题。
源码下载:
链接:https://pan.baidu.com/s/1i6IHpFbXPsmkkVRwVcHuPA
提取码:ecqn
--来自百度网盘超级会员V6勇哥的分享
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路


















