Opencv+Zbar二维码识别(标准条形码/二维码识别)
使用Opencv+Zbar组合可以很容易的识别图片中的二维码,特别是标准的二维码,这里标准指的是二维码成像清晰,图片中二维码的空间占比在40%~100%之间,这样标准的图片,Zbar识别起来很容易,不需要Opencv额外的处理。
下边这个例程演示两者配合对条形码和二维码的识别:
#include "zbar.h"
#include "cv.h"
#include "highgui.h"
#include <iostream> using namespace std;
using namespace zbar; //添加zbar名称空间
using namespace cv; int main(int argc,char*argv[])
{ ImageScanner scanner; scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1); Mat image = imread(argv[1]); Mat imageGray; cvtColor(image,imageGray,CV_RGB2GRAY); int width = imageGray.cols; int height = imageGray.rows; uchar *raw = (uchar *)imageGray.data; Image imageZbar(width, height, "Y800", raw, width * height); scanner.scan(imageZbar); //扫描条码 Image::SymbolIterator symbol = imageZbar.symbol_begin();if(imageZbar.symbol_begin()==imageZbar.symbol_end()){cout<<"查询条码失败,请检查图片!"<<endl;}for(;symbol != imageZbar.symbol_end();++symbol) { cout<<"类型:"<<endl<<symbol->get_type_name()<<endl<<endl; cout<<"条码:"<<endl<<symbol->get_data()<<endl<<endl; } imshow("Source Image",image); waitKey(); imageZbar.set_data(NULL,0);return 0;
}
条形码:
二维码:
这样“标准的”二维码是Zbar非常拿手的,能准确快速的检测出来,包括在条形码外有部分其他信息的,也是小菜一碟:
Zbar很省心,我们还是可以为它做点什么的,比如在一些情况下,需要把条形码裁剪出来,这就涉及到条形码位置的定位,这篇文章准备记录一下如何定位条形码,在定位之后再把裁剪出来的条形码区域丢给Zbar识别读码。
方法一. 水平、垂直方向投影
#include "zbar.h"
#include "cv.h"
#include "highgui.h"
#include <iostream> using namespace std;
using namespace zbar; //添加zbar名称空间
using namespace cv;
//***********************************************
// 函数通过水平和垂直方向投影,找到两个方向上投影的交叉矩形,定位到条形码/二维码
// int threshodValue 投影的最少像素单位
// int binaryzationValue 原图像阈值分割值
//***********************************************
Rect DrawXYProjection(const Mat image,Mat &imageOut,const int threshodValue,const int binaryzationValue);int main(int argc,char*argv[])
{ Mat image = imread(argv[1]); Mat imageCopy=image.clone();Mat imageGray,imagOut; cvtColor(image,imageGray,CV_RGB2GRAY);Rect rect(0,0,0,0);rect= DrawXYProjection(image,imagOut,image.rows/10,100);Mat roi=image(rect);//画出条形码的矩形框rectangle(imageCopy,Point(rect.x,rect.y),Point(rect.x+rect.width,rect.y+rect.height),Scalar(0,0,255),2);imshow("Source Image",image);imshow("水平垂直投影",imagOut);imshow("Output Image",roi);imshow("Source Image Rect",imageCopy);waitKey(); return 0;
} Rect DrawXYProjection(const Mat image,Mat &imageOut,const int threshodValue,const int binaryzationValue)
{Mat img=image.clone();if(img.channels()>1){cvtColor(img,img,CV_RGB2GRAY);}Mat out(img.size(),img.type(),Scalar(255));imageOut=out;//对每一个传入的图片做灰度归一化,以便使用同一套阈值参数normalize(img,img,0,255,NORM_MINMAX);vector<int> vectorVertical(img.cols,0);for(int i=0;i<img.cols;i++){for(int j=0;j<img.rows;j++){if(img.at<uchar>(j,i)<binaryzationValue){vectorVertical[i]++;}}}//列值归一化int high=img.rows/6;normalize(vectorVertical,vectorVertical,0,high,NORM_MINMAX);for(int i=0;i<img.cols;i++){for(int j=0;j<img.rows;j++){if(vectorVertical[i]>threshodValue){line(imageOut,Point(i,img.rows),Point(i,img.rows-vectorVertical[i]),Scalar(0));}}}//水平投影vector<int> vectorHorizontal(img.rows,0);for(int i=0;i<img.rows;i++){for(int j=0;j<img.cols;j++){if(img.at<uchar>(i,j)<binaryzationValue){vectorHorizontal[i]++;}}} normalize(vectorHorizontal,vectorHorizontal,0,high,NORM_MINMAX);for(int i=0;i<img.rows;i++){for(int j=0;j<img.cols;j++){if(vectorHorizontal[i]>threshodValue){line(imageOut,Point(img.cols-vectorHorizontal[i],i),Point(img.cols,i),Scalar(0));}}}//找到投影四个角点坐标vector<int>::iterator beginV=vectorVertical.begin();vector<int>::iterator beginH=vectorHorizontal.begin();vector<int>::iterator endV=vectorVertical.end()-1;vector<int>::iterator endH=vectorHorizontal.end()-1;int widthV=0;int widthH=0;int highV=0;int highH=0;while(*beginV<threshodValue){beginV++;widthV++;}while(*endV<threshodValue){endV--;widthH++;}while(*beginH<threshodValue){beginH++;highV++;}while(*endH<threshodValue){endH--;highH++;}//投影矩形Rect rect(widthV,highV,img.cols-widthH-widthV,img.rows-highH-highV);return rect;
}
通过图像在水平和垂直方向上的投影,按照一定的阈值,找到二维码所在位置,剪切出来用于下一步Zbar条码识别。当然这个方法只能识别出背景简单的图片中的二维码。
条形码效果:
水平、垂直投影
检出条形码区域
二维码效果:
方法二.梯度运算
#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp" using namespace cv; int main(int argc,char *argv[])
{ Mat image,imageGray,imageGuussian; Mat imageSobelX,imageSobelY,imageSobelOut; image=imread(argv[1]); //1. 原图像大小调整,提高运算效率 resize(image,image,Size(500,300)); imshow("1.原图像",image); //2. 转化为灰度图 cvtColor(image,imageGray,CV_RGB2GRAY); imshow("2.灰度图",imageGray); //3. 高斯平滑滤波 GaussianBlur(imageGray,imageGuussian,Size(3,3),0); imshow("3.高斯平衡滤波",imageGuussian); //4.求得水平和垂直方向灰度图像的梯度差,使用Sobel算子 Mat imageX16S,imageY16S; Sobel(imageGuussian,imageX16S,CV_16S,1,0,3,1,0,4); Sobel(imageGuussian,imageY16S,CV_16S,0,1,3,1,0,4); convertScaleAbs(imageX16S,imageSobelX,1,0); convertScaleAbs(imageY16S,imageSobelY,1,0); imageSobelOut=imageSobelX-imageSobelY; imshow("4.X方向梯度",imageSobelX); imshow("4.Y方向梯度",imageSobelY); imshow("4.XY方向梯度差",imageSobelOut); //5.均值滤波,消除高频噪声 blur(imageSobelOut,imageSobelOut,Size(3,3)); imshow("5.均值滤波",imageSobelOut); //6.二值化 Mat imageSobleOutThreshold; threshold(imageSobelOut,imageSobleOutThreshold,180,255,CV_THRESH_BINARY); imshow("6.二值化",imageSobleOutThreshold); //7.闭运算,填充条形码间隙 Mat element=getStructuringElement(0,Size(7,7)); morphologyEx(imageSobleOutThreshold,imageSobleOutThreshold,MORPH_CLOSE,element); imshow("7.闭运算",imageSobleOutThreshold); //8. 腐蚀,去除孤立的点 erode(imageSobleOutThreshold,imageSobleOutThreshold,element); imshow("8.腐蚀",imageSobleOutThreshold); //9. 膨胀,填充条形码间空隙,根据核的大小,有可能需要2~3次膨胀操作 dilate(imageSobleOutThreshold,imageSobleOutThreshold,element); dilate(imageSobleOutThreshold,imageSobleOutThreshold,element); dilate(imageSobleOutThreshold,imageSobleOutThreshold,element); imshow("9.膨胀",imageSobleOutThreshold); vector<vector<Point>> contours; vector<Vec4i> hiera; //10.通过findContours找到条形码区域的矩形边界 findContours(imageSobleOutThreshold,contours,hiera,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE); for(int i=0;i<contours.size();i++) { Rect rect=boundingRect((Mat)contours[i]); rectangle(image,rect,Scalar(255),2); } imshow("10.找出二维码矩形区域",image); waitKey();
}
原图像
平滑滤波
水平和垂直方向灰度图像的梯度差
闭运算、腐蚀、膨胀后通过findContours找到条形码区域的矩形边界
二维码:
原图:
平衡滤波
梯度和
闭运算、腐蚀、膨胀后通过findContours找到条形码区域的矩形边界
Opencv+Zbar二维码识别(标准条形码/二维码识别)相关推荐
- 手机移动端-纯js浏览器h5调用摄像头扫描识别解析 条形码+二维码
一.场景 手机移动端-原生js 浏览器h5 解决 识别二维码 条形码功能: 不借助Hbuilder.需要自己打包成APP,比如用Hbuilder打包,浏览器端项目h5 无打包成app部署 X 不采用 ...
- 服务器维保价格标准_设备维保服务内容及报价
号 服务系统 服务项目 服务内容 备注 1 网络及数据机房 运行维护 UPS 电源系统维护 建立设备维修档案记录设备运行情况,包括 UPS 设备 维修维护卡. UPS 电池测试记录表. UPS 电池放 ...
- 中国二维码--汉信码(中国主导的首个二维码码制国际标准「汉信码」ISO/IEC 20830:2021《信息技术 自动识别与数据采集技术 汉信码条码符号规范》)
国际标准化组织(ISO)和国际电工协会(IEC)正式发布汉信码 ISO/IEC 国际标准 --ISO/IEC 20830:2021<信息技术 自动识别与数据采集技术 汉信码条码符号规范>. ...
- Opencv+ZBar识别条形码、二维码
文章目录 Opencv识别条形码.二维码 1.ZBar环境配置 2.一维码(条形码)识别 3. 二维码的识别 4. Opencv识别二维码 结束 Opencv识别条形码.二维码 最近的一次作业,恰好之 ...
- Linux OpenCV + zBar 实现二维码识别
第一个版本 参考:https://blog.csdn.net/pyt1234567890/article/details/109597353 特点:实现简单.但局限于亮度 清晰度好,没有扭曲变形的情况 ...
- Opencv+Zbar二维码识别(二维码校正)
二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...
- OpenCV检测与识别条码、二维码
原文链接:http://www.juzicode.com/opencv-note-barcodedetector-qrcodedetector 在 zbar:给我来10G打码图片 一文中桔子菌介绍了 ...
- 用不同的QR Code识别库实现二维码的识别(第一篇:opencv 和BoofCV)
最近有个项目需要实现二维码的识别和摄像头的数据采集.在开始正式项目之前,我决定用python写几行简单的代码来测试每个库的识别效果.这次没有连续测量,也没有使用多线程识别.只是简单的测试了每个二维码的 ...
- GM65条形码二维码扫描识别模块与STM32学习
目录 模块介绍: 简介: 原理介绍: 工作流程: 技术参数: 修改配置: 代码介绍: 串口函数: 主函数: 模块介绍: 简介: GM65 条形码二维码扫描识别模块是一种基于激光扫描头的识别设备 原理介 ...
最新文章
- 16 级高代 II 思考题十的多种证明
- CSS文件可维护、可读性提高指南第2/2页
- 什么是Session分布式共享
- C# 8 - Range 和 Index(范围和索引)
- 窗宽窗位改变图像_CT、MRI图像的影像诊断4大原则、5个步骤、3大阅片方法
- VS 错误: 未找到与约束contractname Microsoft.VisualStudio.Utilities.IContentTypeRegistryService...
- 减少上下文切换和避免死锁简述
- 方言 —— 各地方言
- 动态规划相关知识点总结
- cs231n学习记录
- 图灵社区python kindle_推送mobi至Kindle流程说明(简要操作)
- 秀米图文排版转html,秀米微信编辑器图文排版H5秀图文教程
- laravel实现打包多个文件,并下载
- glassfish mysql datasource_GlassFish连接池(GlassFish connection pool)
- 多幸运用计算机演奏的乐谱,多幸运简谱-韩安旭演唱-孙世彦制谱
- 采集本地HTML数据,火车采集器保存为本地word、excel、html、txt文件方法及文件模板_爬虫软件技术与爬虫软件网页数据采集器门户...
- 特征预处理和特征生成 (一)数字特征
- 一个简单的例子解释什么是量子计算机
- 概述知识图谱在人工智能中的应用
- 人脸核身 微信h5_微信小程序人脸核身---快速入门到实战(附开发工具类,复制即用)...
热门文章
- npm - 报错:found XXX vulnerabilities (XXX low, X moderate),run `npm audit fix` to fix them, or `npm au
- 10组团队项目-Beta冲刺-1/5
- Java8 Stream流式操作接口详解
- matlab 根轨迹 虚轴交点,根轨迹与虚轴的交点.ppt
- Navisworks动画制作总结
- AD原理图库元件标识等字符上方的横线
- QT/C++从新手到老手系列之QT中级篇-李浩林-专题视频课程
- 学习无线通信 无线数据传输 要了解那些基本概念
- 软件测试30K*16(总包50W+)入职offer,一位字节跳动女测试开发的自述
- hyper-v虚拟机常用命令