Halcon: Image Acquisition Callback

源代码来自Halcon/IACallback (C#)。IA=Image Acquisition。

想调试Halcon的图像采集部分,就拿了3个AVT Stringray F-201B的相机来测试,发现回调函数部分不支持,所以程序没有完全调通。

整个程序按照这样逻辑来的:Show Available Device -> init device -> Start Acquire Thread-> Show available Callback Types -> Register Callback Type -> Grab Image Start -> Exit Program.

1)ShowAvailableDevice:

显示halcon所支持的图像采集设备的数量,并返回设备数量。如取得采集卡(准确的说应该是相机)的信息,使用

//HOperatorSet.InfoFramegrabber(cInterface, "device", out hv_Information, out hv_BoardList);
HOperatorSet.InfoFramegrabber("GenICamTL", "info_boards", out hv_Information, out hv_BoardList);

源代码中cInterface="GigEVision",相机F-201B并不支持,后来我改为"GenICamTL"就可以了;语句

hv_BoardList.TupleSelect(i).S

取i=0,得到以下相机的信息(前面的"1)"是额外添加的):

1)  | device:DEV_0xA4701130A5F3B | unique_name:DEV_0xA4701130A5F3B | interface:V
imba1394Interface_0x0 | producer:C:\Program Files\Allied Vision\Vimba_2.1\Vimba1
394TL\Bin\Win64\Vimba1394TL.cti | vendor:AVT | model:Stingray F201B | tl_type:II
DC | status:available

2)Init Device:

根据用户的选择打开对应的相机

HOperatorSet.OpenFramegrabber("GenICamTL", 1, 1, 0, 0, 0, 0,
                                "default", -1, "default", -1, "false", "default",
                                gDevices[deviceNumber - 1], -1, -1, out AcqHandle);

第一个参数name还是选择“GenICamTL”,否则还会出现异常。

3)Start Acquire Thread:

使用带参数的线程来异步采集图像

gWorkerThread = new Thread(new ParameterizedThreadStart(DoWork));
gWorkerThread.Start(AcqHandle);
gThreadRunning = true;

输入的HTuple型的参数AcqHandle代表上面我们选择的相机,布尔型的变量gThreadRunning表示线程是否在运行,主体动作DoWork()完成图像的异步采集。

static void DoWork(object AcqHandle)
{
      HOperatorSet.LockMutex(gAcqMutex);
      while (true)
      {
          HOperatorSet.WaitCondition(gAcqCondition, gAcqMutex);

          if (!gThreadRunning || gCountCallbacks > cMaxGrabImage)
              break;

          Console.WriteLine("Thread specific calculations");
          try
          {
              HOperatorSet.GrabImageAsync(out gImage, (HTuple)AcqHandle, -1);
          }
          catch (HalconException ex)
          {
              Console.WriteLine(ex.GetErrorMessage());
          }
      }
      HOperatorSet.UnlockMutex(gAcqMutex);
      Console.WriteLine("End acquisition thread\n");
}

由于是等待信号gAcqCondition,所以没有采集的动作。

4)Show Available Callback Types:

读取相机所支持的回调类型

HOperatorSet.GetFramegrabberParam(hAcqHandle, "available_callback_types", out Value);

输出值Value是个数组,通过以下语句打印结果:

Console.WriteLine(i + 1 + ") " + Value.TupleSelect(i).S);

得到F-20B相机所支持的所有回调(共181个,个人认为很多可以看做属性),如:

1) DeviceVendorName
2) DeviceModelName
3) DeviceFirmwareVersion
4) FirmwareVerMajor
5) FirmwareVerMinor
6) FirmwareVerBuild
7) DeviceMicrocontrollerVersion
8) DeviceSFNCVersionMajor
9) DeviceSFNCVersionMinor
10) DeviceSFNCVersionSubMinor
11) DeviceID
12) DeviceSerialNumber
... ...
180) [Stream]StreamAnnounceBufferMinimum
181) [Stream]DriverBuffersCount

5)Register Callback Type:

根据用户选择的Callback Type与程序中规定的callback(如transfer_end,event_queue_overflow,device_lost)对比,如果都不满足,就需要设置参数,包括EventSelector,EventNotification.

接下来判断是否要注册ExposureEnd,transfer_end并完成相应的注册。定义的delegate:

static HalconDotNet.HalconAPI.HFramegrabberCallback delegateCallback = MyCallbackFunction;

完成注册:

IntPtr ptr = Marshal.GetFunctionPointerForDelegate(delegateCallback);
... ...
HOperatorSet.SetFramegrabberCallback(AcqHandle, gCallbackTypes[callback_number - 1], ptr, myContext);

myContext是一个整型值(0,1,2)代表用户的选择。尝试强制改变myContext=1或2,使下面的MyCallbackFunction循环能够进去,结果没有如我所愿,程序显示:callback not supported.

我们再回到MyCallbackFunction的定义中:

public static int MyCallbackFunction(IntPtr handle, IntPtr user_context, IntPtr context)
{
      int int_context = context.ToInt32();

      if (int_context == (int)myCallbackTypes.EXPOSURE_END ||
        int_context == (int)myCallbackTypes.TRANSFER_END)
      {
        HOperatorSet.LockMutex(gAcqMutex);
        HOperatorSet.SignalCondition(gAcqCondition);
        gCountCallbacks++;
        Console.WriteLine("Send signal to the worker thread");
        HOperatorSet.UnlockMutex(gAcqMutex);
      }

      Console.WriteLine("User specific callback function executed");
      return 0;
}
参数context就是用户的选择,对比选择,然后给采集线程发送信号gAcqCondition就可以开始采集了。

通过对比上一步得到的181个回调类型,发现没有一个与这几个相同,可能是硬件并不支持。

6)Grab Image Start:

为了避免冲突,此处的Grab与线程间的Grab都使用了Halcon中的互斥器Mutex(这不是Windows中的Mutex)

static HMutex gAcqMutex;
... ...
gAcqMutex = new HMutex("", "");
... ...
HOperatorSet.LockMutex(gAcqMutex);
... ...
HOperatorSet.UnlockMutex(gAcqMutex);

知道用户点击Enter结束采集。

7)Exit Program:

退出程序过程包括:取消注册Callback;给线程发送退出信号;等待线程结束;清除资源。

static void exitProgram(HTuple AcqHandle, bool init_device, bool reg_rallback, int callback_number)
{
      HOperatorSet.LockMutex(gAcqMutex);
      if (reg_rallback)
          HOperatorSet.SetFramegrabberCallback(AcqHandle, gCallbackTypes[callback_number - 1], 0, 0);
      HOperatorSet.UnlockMutex(gAcqMutex);

      if (init_device)
      {
          gThreadRunning = false;
          HOperatorSet.SignalCondition(gAcqCondition);

          gWorkerThread.Join();

          HOperatorSet.ClearMutex(gAcqMutex);
          HOperatorSet.ClearCondition(gAcqCondition);
          HOperatorSet.CloseFramegrabber(AcqHandle);
      }
      Environment.Exit(0);
}


猜你喜欢

转载自blog.csdn.net/huan_126/article/details/80253411
今日推荐