怎样使用HALCON.NET类

怎样使用HALCON.NET类,第1张

在HALCON/NET,我们可以用过一个类的实例

(instances of class)来调用HALCON算子。在HalconDotNet引用里,也就是动态链接库里包许多实例化一个类方法,这些

方法可能是重载的,静态的HALCON算子我们可以直接通过类名来调用(这些方法包括HALCON里所有的算子),而非静态的方法必须要通过实例化一个类

后才可以使用,通常HALCON/NET封装了一个类的实例化方法以及类方法。

例如在C++中,可以使用以下两种方法:

1 C++(算子模式)

通过代码导出,以C++为例,默认导出为算子型的语法结构,而非面向对象的;在此模式下,全部函数声明为全局类型,数据类型只需要用Hobject、HTuple两类类型进行声明;

2 C++(面向对象)

可以以面向对象的方式重写代码,也即利用类及类的成员函数;在这种模式下,控制变量的类型仍未HTuple,而图形数据可以由多种类型,如HImage等;

HALCON手册建议使用者使用第二种方法。

例如我们使用第二种方法实现抓取图像序列(imagesequence)里第一张图像,并且将他显示在HWindowControl窗口中。代码是:

[cpp] view plaincopy

private HWindow Window;

private HFramegrabber Framegrabber;

private HImage Img;

Window= WindowControlHalconWindow;

Framegrabber= new HFramegrabber("File", 1, 1, 0, 0, 0, 0, "default",

-1,"default", -1, "default",

"board/boardseq","default", 1, -1);

Img= FramegrabberGrabImage();

ImgDispObj(Window);

GrabImage算子是通过HFramegrabber的实例来调用的。如果你是一个有经验的HALCON使用者,也许你已经看出来HFramegrabber的构造函数调用了OpenFramegraber算子。

但是对于新手来说,可能刚刚接触Halcon,对于Halcon算子还处于熟悉阶段,从Hdevelop中直接到出来的代码也是直接使用静态类。那么建议先使用第一种方法,你只需要明白通过HOperatorSet这个类你可以调用任何一个HALCON算子。

下面我们来看一下到底怎么样调用一个算子。以GrabImage算子为例:

[cpp] view plaincopy

static void HOperatorSetGrabImage (out HObject image, HTuple acqHandle)//静态方法直接调用算子,包含的参数和halcon算子参数完全相同

void HImageGrabImage (HFramegrabber acqHandle)//类中封装的类方法,要先实例化类后才可以使用

HImage HFramegrabberGrabImage ()//重载的方法

image(output_object) image ; HImage

acqHandle(input_control) framegrabber ; HFramegrabber / HTuple

[cpp] view plaincopy

我们可以看出,算子可以通过三个类进行调

用:HOperatorSet, HImage,和HFramegrabber。其中第一种通过HOperatorSet调用主要是用在导出的

HDevelop中(如果你导出程序的话就会看到),也是建议新手使用的方法。而熟悉了之后一般我们在写程序时建议使用另外两种方式,就像下面这样进行调

用:

[cpp] view plaincopy

HImage Image1;

HImage Image4 = newHImage();

HFramegrabberFramegrabber =

newHFramegrabber("File", 1, 1, 0, 0, 0, 0, "default", -1,

"default",-1, "default", "board/boardseq", "default", -1,-1);

Image1 =FramegrabberGrabImage();

HImage Image3 = null;

需要注意的是通过

HFramegrabber调用返回方法的值,而通过HImage调用没有返回值而是调用的类实例被修改,也就是HImage对象被修改。通常,调用类实

例不会被一个算子所修改,除了被上面所看到的“类构造器”(constructor-like)算子调用。

一些算子像CountSeconds可以当做类方法来使用,例如,你可以直接通过类名调用它们而不用生成一个实例:

[cpp] view plaincopy

double S1, S2;

S1 =HSystemCountSeconds();

这是因为这些算子声明前面都有static关键字:

[cpp] view plaincopy

static void HOperatorSetCountSeconds (outHTupleseconds)

static double HSystemCountSeconds()<span style="font-family:'Times New Roman'; font-size:14px; line-height:21px"> </span>

下面我们看一下类的生命周期:从声明(Declaration)到终结(Finalization)

下面的声明仅仅声明了一个类HImage的变量,而没有指向任何的对象:

[cpp] view plaincopy

HImage Image1;

在这个语句中,你不能只使用变量直接去调用算子;有些语言里面甚至不能够将它用做一个输出参数(例如VB 2005)。只有先给它一个图像对象,例如:

[cpp] view plaincopy

Image1 =FramegrabberGrabImage();

你也可以在声明的时候初始化一个变量:

[cpp] view plaincopy

HImage Image2 =FramegrabberGrabImage();

[cpp] view plaincopy

<span style="font-family:Arial,Helvetica,sans-serif"></span><pre name="code" class="cpp">HImage Image3 = null;</pre>

你可以通过一个IsInitialized方法来检验一个类实例是否被初始化。

但是使用构造函数(Constructors)后的对象就可以了:

下面的式子是利用类HImage空的构造函数来初始化一个类变量

[cpp] view plaincopy

HImage Image4 = new HImage(); <span style="font-family:'Times New Roman'; font-size:14px"> </span>

类实例可以用来调用“类似构造函数”算子像GrabImage,用抓住的一张初始化类变量:

[cpp] view plaincopy

Image4GrabImage(Framegrabber);

除了空的构造器,大部分HALCON/NET类提供一个或者更多的构造器来初始化基于HALCON算子的对象。例如,HImage提供了一个构造器:

[cpp] view plaincopy

HImage Image5 = newHImage("fuse");<span style="font-family:'Times New Roman'; font-size:14px; line-height:21px"> </span>

reference manual和右键go to definition是很好的参考资料。

关于Finalizers

在NET中程序员不需要考虑内存管理方面的事情,因为它有自动垃圾回收回收哪些不再使用的对象。HALCON/NET完全遵循这种规则通过提供所有类的回收器,所以不需要管理资源,例如,一个图像采集设备的连接会被自动正确的删除。

对于大部分类,回收器自动调用合适的算子像CloseFramegrabber来释放资源。调用的算子在一个参考手册页中列了出来(例如HFramegrabber)。这个算子不可以通过类来调用,在相应的参考手册条目中可以看到:

[cpp] view plaincopy

static void HOperatorSetCloseFramegrabber (HTupleacqHandle)

也就是说你没有必要调用这样一个算子,如果你想用别的参数从新进行连接,它会自动执行。

注意当用HFramegrabber一般的类时不能使用HOperatorSet来关闭或者清除算子。

但是对于像图像这种数据变量,它们包含的只是引用,对于他们指向的内存垃圾回收机制也许不会直接清除,这些就需要手动清除:

有一种方法是在处理完事件后直接调用GC清除:

[cpp] view plaincopy

private void Timer_Tick(object sender, SystemEventArgs e)

{

Action();

GCCollect();

GCWaitForPendingFinalizers();

}

另一种方法是直接调用自带的销毁方法:

[cpp] view plaincopy

HImage Image = new HImage("fuse");

ImageDispose();

最近看到一个例子,来自一个论坛,提问者想要计算图中木头的数量,悬赏了分值但是没人回复,我看到的时候这帖子已经过去好几年了。作为一个肤浅的初学者,我觉得这问题很有趣,所以打算从这个例子入手,研究下Halcon中的图像处理。

首先,从二值化开始,这张图在刚开始二值化之后出现一些问题。阈值设的高了,会弱化边角一些木头的局部区域,设的低了,会造成一些粘连。而且图像中还有一些干扰。如何在保留边角局部信息的情况下尽可能的防止粘连,是个问题。

结合这个问题,我的思路是分两步走。先把边角一些小的木头区域提取出来,再专门解决粘连的问题,问题得到了解决。

区分大小的依据主要是面积,在做了一些基本的预处理之后,可以把较小的一部分区域图像,如靠近四个边的部分木头,先分割出来了。这个过程中,需要对木头边缘做一些处理,去掉外圈的树皮,和一些干扰的区域,提取出木头截面的大块部分。

得到下图:

这一步就比较简单了,没有小面积区域的顾虑,可以做下腐蚀,让边缘更加清晰。这样就分割开来了。

把上一部分割出的大小区域分别合并,即得到木头的总数了。

btw:这个例子我也做过分水岭算法的测试,但是效果不尽如人意,主要是分割出来的区域太多了,比如图中那片白色的干扰物、右小方的竹棍等,也分割出来了。而边角一些木头的边缘区域又很难顾及到。也可能是参数设置的不够好,所以这个算法我还在研究。

以上是我自己的一些浅薄的思路,希望随着学习的深入,能发现更好的方式。

以上就是关于怎样使用HALCON/.NET类全部的内容,包括:怎样使用HALCON/.NET类、Halcon粘连图象分割与计数、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9647430.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存