[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 ...
随机推荐
- day8 基本数据类型之字典
day8 基本数据类型之字典 一.字典(dict) 1.用途: 2.定义方式:在{}内用逗号分隔开多个元素,每个元素都是key:value的形式,其中value可以使任意类型,而key必须是不可变类型 ...
- 如何让Linux 机器CPU使用率变高
如何让Linux 机器CPU使用率变高 一.实现 1.单行命令搞定 for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" ...
- HDFS初探之旅(一)
1.HDFS简介 ...
- 设置linux下oracle开机自启动
1.修改配置文件,vi /etc/oratab orcl:/u01/app/oracle/product/11.2.0/db_1:Y 2.创建启动文件,/etc/init.d/ #!/bin/sh # ...
- 实时数据同步inotify+rsync
inotify inotify是一个实时监控服务,他能实时监控服务器中的目录的变化,发现目录中变化后,在配合rsync服务推送到备份服务器上 inotify要求内核要在2.6.13或之上,通过noti ...
- 基于阿里云 ecs 使用 docker 方式部署 showDoc
官网文档:https://www.showdoc.cc/help?page_id=65610 (建议先看下这个) 首先说明一下,我 ecs 镜像是 CentOS 7.6 64位 1. 首先在 服务器上 ...
- shell脚本 mysql-binlog分析
一.简介 介绍 分析binlog工具,现有功能: 基于业务表分析统计各个表的dml的次数. 各个业务表的最后访问时间. 各dml总的次数. 该binlog的事务总数. 基于业务表的binlog to ...
- 【模型推理】量化实现分享一:详解 min-max 对称量化算法实现
欢迎关注我的公众号 [极智视界],回复001获取Google编程规范 O_o >_< o_O O_o ~_~ o_O 大家好,我是极智视界,本文剖析一下 m ...
- 基于bootstrap的模态框使用
使用步骤两步 1:按顺序引入以下三个文件 <link rel="stylesheet" href="../css/bootstrap.min.css"&g ...
- Java Web三大组件之过滤器(Filter)
什么是过滤器?有什么用? 过滤器JavaWeb三大组件之一,它与Servlet很相似.不过滤器是用来拦截请求的,而不是处理请求的.过滤,顾名思义,就是留下我们想要的,丢掉我们不需要的.例如:某个网站的 ...