简单回顾一下:第一段内容:界面库、算法库、编译器、插件的选择与配置;软件架构;界面架构;数据结构;线程分配。第二阶段内容:绘图模块;相机模块;通信模块;图像保存模块。
第一段是软件的起步阶段,主要是做一些软件框架,第二阶段开发的都是一些独立且必须的软件模块。
如果把整个视觉软件比作一辆车,前面两个阶段我只是把外形架子和轮子造起来,而算法就是发动机。所以我一直认为视觉软件,算法才是核心,软件不管你用什么语言,最终的目的都是交互,而不是决定一个项目成败的关键。
之前我在某视觉公司专职做过两年的算法工程师,略有心得,算法部分我打算分两阶段完成,第一阶段是开发算法架构,第二阶段开发具体的算法模块。
这一阶段,我主要设计了算法架构,其中包括如下几个部分:
1.如何将算法和界面实现分离
2.主程序如何调用算法
3.算法模块基类及子类设计
4.算法模块接口设计
5.算法模块的批处理编译及单元测试
具体设计方案如下:
1.如何将算法和界面实现分离
简单分析下市面上典型的三种做法:
a)简单非标软件的做法,将算法封装成一个process函数,将图片和一些必要参数传入,将结果传出。所有的算法及算法逻辑都在process函数处理。这种做法应该也是新手最常见方法。优点是简单、定制化;缺点是不灵活,算法复用率几乎没有,也就是来一个项目开发一个process。不管你是在什么公司,我不建议这种模式,因为时间久了,你会发现自己的工作重复性很大,耗时耗力,不好维护。
b)标准的工具流程图做法,设计一个算法基类,提供算法的接口和结果,每个算法模块的具体实现在子类,所有算法都是可独立运行,可组合运行,通过界面来组合交互,例如基恩士XG系列、凌云、奥普特都是采用该模式,你可以在界面上拖动一些算法,然后将算法的输入输出通过线条连接组合。这种模式灵活性强,但开发难度较高,调试难度高,一般只有大规模视觉公司会采用。
c)标准的工具积木做法,算法设计原理类似于b),但是界面的交互是通过工具块的形式添加,每个工具都是独立的个体,然后用一个脚本文件或者开发一个界面去获取这些工具的结果,进行一些逻辑判断。例如基恩士CV系列,这种模式较为灵活,操作比较傻瓜式,算法封装性较b)更强,灵活性又较a)更强,是一种比较折中的设计模式。一般的设备厂或小型视觉公司会使用。这里,我采用c)这种模式。
2.主程序如何调用算法;3.算法模块基类及子类设计;4.算法模块接口设计
算法基类提供始化算法、运行算法两个接口,初始化算法包括传递算法参数、初始化模板等只需要操作一次的内容;运行算法包括处理、赋值、判定、分类,最后将结果传递出去。交互逻辑如下:
主程序实例化算法对象——>界面设计参数——>算法初始化——>算法运行——>显示算法结果——>脚本界面组合所有算法结果并做出最后判定——>OK/NG通信输出
其中,多个算法模块的运行可采用线程池并行处理,加速。或采用OMP/SSE/GPU等加速方法,后期会单独对算法加速进行总结,这里不扩展。
5.算法模块的批处理编译及单元测试
算法模块一般是最容易出bug的地方,而且是致命级别的。所以算法一定要有自己的单元测试,这里推荐使用goole test,每个算法模块尽可能完善测试用例,以单元测试的形式进行结果预期评估,然后写个批处理运行所有测试用例,这样每次发布算法的时候都会通过测试用例来筛选出一些低级的算法错误。有兴趣的朋友可以研究下cmake和gooltest的配合使用。
下个阶段计划:完成标准算法模块、及瑕疵、划痕的非标算法模块