[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 标志,反变换
*/
[opencv]二维码识别开发流程及问题复盘总结的更多相关文章
- [opencv]二维码识别率提升方案-resize调整
这里采用循环resize的方式,对二维码图像进行放缩. 识别到name(二维码结果)不为空,则立即退出循环 //循环识别 for (int i = 1;name.empty(); i++){ resi ...
- 基于opencv+python的二维码识别
花了2天时间终于把二维码识别做出来了,不过效果一般,后面会应用在ROS辅助定位上,废话少说先上图: 具体过程参考了这位大神的博客:http://blog.csdn.net/qq_25491201/ar ...
- Opencv+Zbar二维码识别(二维码校正)
二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...
- android 图片二维码识别和保存(二)
续上一篇,开发图片二维码识别功能后,我们对功能进行性能分析内存占用显著提高了,不使用该功能内存占用大约是147M,使用这个功能多次以后,高达203M. 因此对功能进行研究,发现每次生成的图片没有即时的 ...
- Python zxing 库解析(条形码二维码识别)
各种扫码软件 最近要做个二维码识别的项目,查到二维码识别有好多开源的不开源的软件 http://www.oschina.net/project/tag/238/ Zbar 首先试了一下Zbar,pyt ...
- 基于opencv3.0和下的条形码与二维码识别
其中对条码与二维码的识别分为以下4个步骤 1. 利用opencv和Zbar(或者Zxing)对标准的条形码图片(即没有多余背景干扰,且图片没有倾斜)进行解码,将解码信息显示出来,并与原始信息对比. 2 ...
- android 图片二维码识别和保存(一)
最新业务开发二维码识别的功能,这个功能,在很多应用上都有,比如微信长按图片识别二维码,如果图片中存在可以识别的二维码时,可以增加一个选项 识别二维码.那么如何去实现这个功能呢.这里其实也非常简单,首先 ...
- 使用zxing二维码识别
1.多二维码识别 (同一张图片中多二维码识别) 直接上代码舒服: pom文件: <!-- QR Code --> <dependency> <groupId>com ...
- 第47章 QR-Decoder-OV5640二维码识别—零死角玩转STM32-F429系列
第47章 QR-Decoder-OV5640二维码识别 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.y ...
随机推荐
- day01互联网架构理论
- Android中的性能优化
由于手机硬件的限制,内存和CPU都无法像pc一样具有超大的内存,Android手机上,过多的使用内存,会容易导致oom,过多的使用CPU资源,会导致手机卡顿,甚至导致anr.我主要是从一下几部分进行优 ...
- archive后upload to app store时遇到app id不可用的问题
问题如下图 出现此问题的原因有两种: 1.此app id在AppStore中已经存在,也就是说你使用别人注册的app ID , 如果是这样,你只能更换app ID 2.此app ID是自己的,突然之 ...
- vue-cli2嵌入html
1.使用iframe <!-- 相对路径/绝对路径 --> <iframe src="../../../static/zsw.html"></ifra ...
- SpringBoot自定义控制层参数解析
一.背景 在Spring的Controller中,我们通过@RequestParam或@RequestBody就可以将请求中的参数映射到控制层具体的参数中,那么这个是怎么实现的呢?如果我现在控制层中的 ...
- uniapp实现钉钉扫码登录
由于uniapp暂无钉钉授权登录所以本文将钉钉扫码登录作为网页嵌入uniapp,最终实现钉钉扫码登录app 1. 用H5调起钉钉扫码登录 钉钉在网页端的扫码登录可参考钉钉文档:扫码登录第三方网站 - ...
- LeetCode 36. Valid Sudoku (Medium)
题目 Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according ...
- STM32F103ZET6 核心板制作指引
学点啥系列之 --STM32F103ZET6 核心板制作指引 原创资料,转载请联系 作者的话:会画stm32F103ZET6的话,rct6啥的简直不要太简单 一.电路总览 图1:电路整体 二.单片机部 ...
- 替DateDif哭诉一把(Excel函数集团)
Excel中有个工作表函数DateDif,专门用来计算两日期之间的日差.月差.年差,传说十分好用. 具体用法在此就省略了,好奇的童鞋请自行*度~ 可是,在Excel里,他却是个"没户口&qu ...
- java 输入输出IO 转换流-字符编码
编码和其产生的问题: 计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字.英文.标点符号.汉字等字符是二进制数转换之后的结果. 按照某种规则,将字符存储到计算机中,称为编码 .反之,将存 ...