最近接手一个项目,需要利用IDS双网口相机出图,并计算目标物体的解像力和均匀性。
IDS双相机分别获取目标物体一部分的外型图案,在VS C++中利用MFC多文档编程(已有大致框架),并进行算法设计和程序设计。因为数据获取涉及到了两个外部硬件,且需要同步实现数据获取,以及后续的计算,特考虑使用多线程的方式进行程序设计。
初步的设计思想是:以相机为分析对象,为每个相机开辟三个线程,分别进行图像的采集、图像的显示和图像的处理。但在实际的设计时发现,初始化使用两个线程即可,图像处理的数据可以直接从图像显示线程中取得,只要设计标志位就可以防止图像处理线程中的数据被显示线程中更新的数据覆盖。
为此,程序初始化时给左相机开辟两个事件线程,也给右相机开辟两个事件线程,分别进行图像的采集和图像的显示。当然,在程序的运行中,还需要给图像的处理计算开辟图像测试线程(区别上面两类线程)。
程序简单的动作流程如下:
特别注意的是,每个相机线程中的数据有互相访问的特点,为了防止显示的数据不被下一次采集到的数据给刷掉(同一时间两个动作访问同一个内存块,访问冲突!),以及防止处理的数据不被下一次显示的数据给刷掉,需要在数据被完全写进内存后,设置标志位,防止其它的线程同时操作内存!
处理的方式可以是,程序初始化时,标志位置-1(表示可以进行数据的采集),数据的采集成功后,标志位置1(表示可以进行数据的显示),数据的显示成功后,标志位置2(表示可以进行数据的处理),数据的处理成功后,标志位置-1(表示可以下一次循环,进行数据的采集)。
当然,以上有一个问题,数据的采集必须要等数据处理完毕后才能进行!优化方式是在数据采集成功后,将数据复制两份,一份用于显示,一份用于处理,这样可以提高数据的采集速度(以上示意图需要改动!如下图)。
需要注意的是,当检测到没有处理时,数据的线程还是要正常进行,所以需要两类的标志位,一类负责 采集+显示,一类负责 采集+显示(+处理)。如下:
if ( theApp.leftTempSaveOK==-1 ) //满足条件,则缓存数据
{
memcpy(...);//具体操作省略
theApp.leftTempSaveOK=1; //缓存成功后,置1
if ( theApp.leftProcessOK == -1 )//处理数据缓存
{
memcpy(...);//具体操作省略
theApp.leftProcessOK=1;//缓存成功后,置1,表示可以随时利用此数据进行图像处理!
}
}
目前已实现利用IDS双相机进行目标物体的实时测试,但是有一个问题是,所购的IDS相机帧率较低(才12fps),画面明显不连续(正常至少20fps,人眼才不易察觉)。这也说明软件人员也需要懂硬件,还要在研发设计阶段与其他行业的成员充分讨论需求,充分认真评估项目可行性,否则后续开展工作会遇到各种问题!