使用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二维码识别(标准条形码/二维码识别)相关推荐

  1. 手机移动端-纯js浏览器h5调用摄像头扫描识别解析 条形码+二维码

    一.场景 手机移动端-原生js 浏览器h5 解决 识别二维码 条形码功能: 不借助Hbuilder.需要自己打包成APP,比如用Hbuilder打包,浏览器端项目h5 无打包成app部署 X 不采用 ...

  2. 服务器维保价格标准_设备维保服务内容及报价

    号 服务系统 服务项目 服务内容 备注 1 网络及数据机房 运行维护 UPS 电源系统维护 建立设备维修档案记录设备运行情况,包括 UPS 设备 维修维护卡. UPS 电池测试记录表. UPS 电池放 ...

  3. 中国二维码--汉信码(中国主导的首个二维码码制国际标准「汉信码」ISO/IEC 20830:2021《信息技术 自动识别与数据采集技术 汉信码条码符号规范》)

    国际标准化组织(ISO)和国际电工协会(IEC)正式发布汉信码 ISO/IEC 国际标准 --ISO/IEC 20830:2021<信息技术 自动识别与数据采集技术 汉信码条码符号规范>. ...

  4. Opencv+ZBar识别条形码、二维码

    文章目录 Opencv识别条形码.二维码 1.ZBar环境配置 2.一维码(条形码)识别 3. 二维码的识别 4. Opencv识别二维码 结束 Opencv识别条形码.二维码 最近的一次作业,恰好之 ...

  5. Linux OpenCV + zBar 实现二维码识别

    第一个版本 参考:https://blog.csdn.net/pyt1234567890/article/details/109597353 特点:实现简单.但局限于亮度 清晰度好,没有扭曲变形的情况 ...

  6. Opencv+Zbar二维码识别(二维码校正)

    二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...

  7. OpenCV检测与识别条码、二维码

    原文链接:http://www.juzicode.com/opencv-note-barcodedetector-qrcodedetector ​在 zbar:给我来10G打码图片 一文中桔子菌介绍了 ...

  8. 用不同的QR Code识别库实现二维码的识别(第一篇:opencv 和BoofCV)

    最近有个项目需要实现二维码的识别和摄像头的数据采集.在开始正式项目之前,我决定用python写几行简单的代码来测试每个库的识别效果.这次没有连续测量,也没有使用多线程识别.只是简单的测试了每个二维码的 ...

  9. GM65条形码二维码扫描识别模块与STM32学习

    目录 模块介绍: 简介: 原理介绍: 工作流程: 技术参数: 修改配置: 代码介绍: 串口函数: 主函数: 模块介绍: 简介: GM65 条形码二维码扫描识别模块是一种基于激光扫描头的识别设备 原理介 ...

最新文章

  1. 16 级高代 II 思考题十的多种证明
  2. CSS文件可维护、可读性提高指南第2/2页
  3. 什么是Session分布式共享
  4. C# 8 - Range 和 Index(范围和索引)
  5. 窗宽窗位改变图像_CT、MRI图像的影像诊断4大原则、5个步骤、3大阅片方法
  6. VS 错误: 未找到与约束contractname Microsoft.VisualStudio.Utilities.IContentTypeRegistryService...
  7. 减少上下文切换和避免死锁简述
  8. 方言 —— 各地方言
  9. 动态规划相关知识点总结
  10. cs231n学习记录
  11. 图灵社区python kindle_推送mobi至Kindle流程说明(简要操作)
  12. 秀米图文排版转html,秀米微信编辑器图文排版H5秀图文教程
  13. laravel实现打包多个文件,并下载
  14. glassfish mysql datasource_GlassFish连接池(GlassFish connection pool)
  15. 多幸运用计算机演奏的乐谱,多幸运简谱-韩安旭演唱-孙世彦制谱
  16. 采集本地HTML数据,火车采集器保存为本地word、excel、html、txt文件方法及文件模板_爬虫软件技术与爬虫软件网页数据采集器门户...
  17. 特征预处理和特征生成 (一)数字特征
  18. 一个简单的例子解释什么是量子计算机
  19. 概述知识图谱在人工智能中的应用
  20. 人脸核身 微信h5_微信小程序人脸核身---快速入门到实战(附开发工具类,复制即用)...

热门文章

  1. npm - 报错:found XXX vulnerabilities (XXX low, X moderate),run `npm audit fix` to fix them, or `npm au
  2. 10组团队项目-Beta冲刺-1/5
  3. Java8 Stream流式操作接口详解
  4. matlab 根轨迹 虚轴交点,根轨迹与虚轴的交点.ppt
  5. Navisworks动画制作总结
  6. AD原理图库元件标识等字符上方的横线
  7. QT/C++从新手到老手系列之QT中级篇-李浩林-专题视频课程
  8. 学习无线通信 无线数据传输 要了解那些基本概念
  9. 软件测试30K*16(总包50W+)入职offer,一位字节跳动女测试开发的自述
  10. hyper-v虚拟机常用命令