[opencv]二维码识别开发流程及问题复盘总结

 

项目复盘总结

开发需求:

在桌面机器人(向下俯视)摄像头拍摄到的图像中做条形码识别与二维码识别。

条形码在图像固定位置,二维码做成卡片的形式在固定区域内随意摆放。

开发环境及相关库:ubuntu 18.04 + Clion + opencv4.1.0 + zxing + zbar

 

开发思路及识别流程:

摄像头拍摄图像分辨率为640*480

1. 图像画面还原校正

由于摄像头(俯视)拍摄到的图像存在线性的透视偏差,类似于车辆行驶的车道线,两条相交的直线,因为透视效应直线向视距远处集中。

此处采用透视变换还原图像为正视图,这里存在一个倾角计算的问题。

根据图像分辨率与实际物体大小的比例进行计算,得出透视变换所需的四个基本点。

 

2. 抓取条形码区域

由于识别条形码的位置为固定,确定了矫正方式后,因此就有以下几种方式将条形码矫正回来。

(1)将截取的固定区域做透视变换区域

(2)将整个图像画面做透视变换区域,再做整个画面的区域截取。

经过验证,最终采用(2)方式,因为摄像头出厂设置有相对误差,不容易计算透视变换的四个基本点。

而针对整个画面和实际图像的比例可以基本确定,故通过(2)要优化(1)。缺点是透视变换的矩阵太大,会加长总时间。

 

3.抓取二维码区域

由于二维码卡片在整个画面中的位置是随机摆放的,同时二维码卡片与画面背景之间有严格的边界。

因此考虑从二维码卡片的轮廓入手,这是抓取卡片区域的大方向。

如何将二维码轮廓与背景其他轮廓分开,这里涉及到比较针对性的预处理方式。

考虑以下几种方式

(1)从Canny图像中查找到的轮廓集合做面积和长宽比例限制上的筛选,调整相关参数,从而得出符合要求的二维码区域

(2)针对查找的轮廓集合做多边形拟合,卡片为四边形区域,因此拟合顶点为4。

(3)在查找的轮廓中,根据二维码的三个矩形区域做轮廓层级的hierarchy层级筛选

经过验证,最终采用(2)方式,虽然(1)也能截取到二维码区域,但卡片区域轮廓的包围矩形无法修正透视变换后存在的形变拉伸,以及存在无法识别到旋转倾斜角度过大的问题。

使用(2)方式的好处是,经过拟合后的四边形轮廓可以直接得到卡片区域的四个角点。

但使用轮廓拟合方式也存在一定的问题,即拟合到的四边形轮廓数量过多,实际上只需要一个。因此需要将多余的筛选掉。

同时四边形轮廓的角点在轮廓集合内是无序的,因此需要根据需求,将四个角点进行与透视变换对应的排序。

照猫画虎,根据排序好的四个角点代入到透视变换,得出校正正视图。此处透视变换的参数,为了与二维码的长宽比适应,透视变换的size长宽比设置为1:1

   

4.识别条形码与二维码

由于zxing和zbar库在性能与识别率上各有千秋,总体来说在当前集成的环境中,zbar高于zxing,但zbar识别不到的部分能被zxing识别出来。

因此考虑使用zxing与zbar混合识别的方式,先走zbar后走zxing。

 

 

遇到的问题及相关解决方案:

1.硬件问题:摄像头角度倾角过大

从而导致透视变换处理之后的图像仍然达不到识别库的要求。

解决方案:摄像头硬件参数调校。

 

2.环境:光照问题

在强光照射下,二维码的部分黑色区域由黑色转变成绿色或红色,造成一定程度上的失真。

解决方案:自适应亮度调节,亮度增强

 

3.图像矫正本身的缺陷

透视变换的插值方式会在一定程度上造成图像失真或增强不必要的白噪声。

默认使用的是 INTER_LINEAR 方式,经测试验证,INTER_CUBIC方式更加适合条形码与二维码在变换中的插值。

/***
* 默认插值方式 INTER_LINEAR = 1 双线性插值
* INTER_NEAREST = 0最近邻插值
* INTER_CUBIC = 2 三次样条插值
* INTER_AREA = 3 区域插值.图像放大时类似于线性插值,图像缩小时可以避免波纹出现。
* INTER_LANCZOS4 = 4 使用8×8像素邻域的Lanczos插值
* INTER_LINEAR_EXACT = 5 位精确双线性插值
* INTER_MAX = 7 插值码掩码
* WARP_FILL_OUTLIERS = 8 标志,填充所有目标图像像素。如果其中一些与图像,设置为零
* WARP_INVERSE_MAP = 16 标志,反变换
*/


posted @ 2020-04-22 15:40  Xu_Lin  阅读(1097)  评论(0编辑  收藏  举报