OpenCV是一个由因特尔公司支持的开源机器视觉库,关于它的介绍,网上随便一搜就车载斗量。这里我不谈视觉库的主要内容,而是将这段时间来对它的使用心得作个简单介绍,以启发打算用这个库的朋友的思路,与大家一起来分享。
在学校的时候,虽然是图像处理研究方向,但真正具体的应用到图像的很多东西,还是在参加工作以后的事。以前在处理图像的时候,我们从不担心速度的问题,以为计算机硬件发展到今天,无所不能的了,双核乃至四核的处理速度简直要赶上宇宙飞船了。但用在机器视觉上,那又是另外一码事。通常而言,机器视觉要求对图像的处理速度都是以毫秒为单位,具体而言是几点几个毫秒,硬件再硬,如果算法不好,速度就永远提不上去,所以速度还是至关重要的东西,并不是所谓由硬件技术就决定了的。
速度是一个方面,精度又是另一个重要方面了。视觉中对精度的要求,通常是以亚像素标准来衡量的。所以对图像处理的算法,不是一般的算法来解决,往往都得使用子像元算法,这样才能达到亚像素标准。通常我们对一幅图像的像素坐标都是用整数计算,但在机器视觉中普遍采用亚像素标准,都是浮点数来计算的。但有的虽然写出来的是浮点数,未必就是用的子像元算法,它的结果根本就不是亚像素。视觉中精度的要求,也是要求极高,一般以微米为计量单位,像几点几个微米,而只有使用子像元算法才能真正达到这个要求。
总的说来,目前国内还没有一个真正意义上的成功的机器视觉开发包,国内的机器视觉方面的大公司基本上还是以代理国外的软件为主。一方面固然是国内的起步晚,但我觉得更多原因还是国内在这方面没有下功夫去做一些基础性的研究工作,总是靠代理别人的东西来实现一个视觉系统的开发。而OpenCV就是一个在机器视觉方面基础工作做得最好的。
总的说来,OpenCV提供的函数库涉及的方面很广,图像处理功能强大,但它仅仅是供研究的一个基础的东西,并不是一计膏药,往哪一贴哪就好使。我们只有在借助它提供的一些基础功能上进行深入研究,才能开发出属于自己的产品来。
OpenCV作为一个开源的函数库,为我们提供了很多方便,看它的源代码,确实有很多值得学习的独到地方。但作为开源的,局限也就在此。它的很多东西并不是最优的,如果真要那样,直接就可以拿来在商业上运用了。所以,我们只有不断的对它进行改造,才能更贴近我们的应用,这里结合我在使用的几处加以说明。
首先是图像的定位。OpenCV也提供了一个图像匹配的函数,这个函数还是写的不错的,但要直接用到商业上就不行了。因为它的处理速度很慢,精度也不是亚像素的,而且没有旋转。它仅仅是一个单纯的灰度定位。要怎么用好这个函数呢,在使用这个函数的时候,我还是下了很多功夫的,对此做了一些改进,让它真正的实现了商业价值。如今我用OpenCV编写的定位软件,其速度和精度丝毫不比国外的那些名牌软件差多少,像halcon和sapera这样的软件巨头,我用OpenCV做出来的定位效果,比如一幅分辨率为1280*1024的图像,它们的速度是几个毫秒,而我做出来的多3至4个毫秒,精度也差不多,但由于OpenCV本身不是亚像素的局限所在,所以精度通常在一个像素左右。
再说几何定位,halcon是采用基于几何形状的算法来进行定位的,可以说做得非常的好,好就好在它的模版图像形状可以任意选取,任意旋转。而Sapera的基于边缘轮廓的定位还要上一个层次,关于它的算法,目前还没有人了解,至今还是个谜。在很多机器图像定位上,几何定位效果更好,更准确。灰度定位在一些图像区域直方图相近似的情况下,往往很难找准目标区域。而几何定位,根据区域的几何特征来做出判断,不单准确,而且执行起来效率更高。目前我用OpenCV做的几何定位总体上说效果还不错,但精度还赶不上,在图像边缘的离合上还不那样准确,不过在后续的研究中,还是会赶上的。
一般而言,对于图像的目标区域都是有形状的,但在实际运用中,我遇到一个客户只要求定位直线的,由于直线不属于一个有形状的区域,它的特征很难描述,所以看似最简单的却最难办。OpenCV采用Hough变换来检测直线和圆,效果也并不好。因为Hough变换的实质也就是两种不同空间的映射,它在噪声大的图像中,检测出来的结果千奇百怪。所以要准确的找到边,必然对图像做好预处理,让处理后的边缘很明显表现出来,再进行Hough检测就容易多了。
在机器视觉中,Blob分析是要经常遇见的,OpenCV也有Blob跟踪的实例,但我没去认真用过,而是自己做了个算法采用它也实现了,且效果也不错。我在做一个啤酒瓶磨具号码检测的项目里,就调用了自己设计的Blob分析算法,效果都还不错。
在具体使用中,往往要用到我们自己定义的图像类型,于是又把OpenCV里的IplImage结构进行了改造,然后定义了属于自己的图像类,可以随意读取,这样方便了很多。其实OpenCV里面对文件的操作写得相当好,非常方便。
总的来说,OpenCV是一个非常不错的开源项目,有很多东西需要我们去学习。但它的源代码,要读明白也非易事。因为它涉及到大量的宏定义,很多函数语句都是些宏定义在里面,还互相嵌套,看起来相当的困难。而且本人接触它的时间也不过两三个月,所以理解得也不透彻。还得一边用、一边学,在实践中摸索和消化。在此只为提示一个思路而言,其中算法不便言明,否则老板看见,定然要批评了。商场如战场,一切都要做好保密工作,哈哈!