二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图:

这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~。

这里介绍一种二维码校正方法,通过定位二维码的4个顶点,利用仿射变换校正。基本思路:滤波->二值化->膨胀(腐蚀)操作->形态学边界->寻找直线->定位交点->仿射变换校正->Zbar识别。

滤波、二值化:

腐蚀操作:

形态学边界:

寻找直线:

角点定位:

仿射变换校正:

Zbar识别:

Code实现:

#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[])
{
Mat imageSource=imread(argv[1],0);
Mat image;
imageSource.copyTo(image);
GaussianBlur(image,image,Size(3,3),0); //滤波
threshold(image,image,100,255,CV_THRESH_BINARY); //二值化
imshow("二值化",image);
Mat element=getStructuringElement(2,Size(7,7)); //膨胀腐蚀核
//morphologyEx(image,image,MORPH_OPEN,element);
for(int i=0;i<10;i++)
{
erode(image,image,element);
i++;
}
imshow("腐蚀s",image);
Mat image1;
erode(image,image1,element);
image1=image-image1;
imshow("边界",image1);
//寻找直线 边界定位也可以用findContours实现
vector<Vec2f>lines;
HoughLines(image1,lines,1,CV_PI/150,250,0,0);
Mat DrawLine=Mat::zeros(image1.size(),CV_8UC1);
for(int i=0;i<lines.size();i++)
{
float rho=lines[i][0];
float theta=lines[i][1];
Point pt1,pt2;
double a=cos(theta),b=sin(theta);
double x0=a*rho,y0=b*rho;
pt1.x=cvRound(x0+1000*(-b));
pt1.y=cvRound(y0+1000*a);
pt2.x=cvRound(x0-1000*(-b));
pt2.y=cvRound(y0-1000*a);
line(DrawLine,pt1,pt2,Scalar(255),1,CV_AA);
}
imshow("直线",DrawLine);
Point2f P1[4];
Point2f P2[4];
vector<Point2f>corners;
goodFeaturesToTrack(DrawLine,corners,4,0.1,10,Mat()); //角点检测
for(int i=0;i<corners.size();i++)
{
circle(DrawLine,corners[i],3,Scalar(255),3);
P1[i]=corners[i];
}
imshow("交点",DrawLine);
int width=P1[1].x-P1[0].x;
int hight=P1[2].y-P1[0].y;
P2[0]=P1[0];
P2[1]=Point2f(P2[0].x+width,P2[0].y);
P2[2]=Point2f(P2[0].x,P2[1].y+hight);
P2[3]=Point2f(P2[1].x,P2[2].y);
Mat elementTransf;
elementTransf= getAffineTransform(P1,P2);
warpAffine(imageSource,imageSource,elementTransf,imageSource.size(),1,0,Scalar(255));
imshow("校正",imageSource);
//Zbar二维码识别
ImageScanner scanner;
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
int width1 = imageSource.cols;
int height1 = imageSource.rows;
uchar *raw = (uchar *)imageSource.data;
Image imageZbar(width1, height1, "Y800", raw, width * height1);
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;
}
namedWindow("Source Window",0);
imshow("Source Window",imageSource);
waitKey();
imageZbar.set_data(NULL,0);
return 0;
}

Opencv+Zbar二维码识别(二维码校正)的更多相关文章

  1. Flutter扫码识别二维码内容

    前面一篇写了生成二维码图片,这篇来写使用相机扫描识别二维码 识别二维码需要用到插件 barcode_scan 首先在 pubspec.yaml 文件中添加以下依赖,添加依赖后在 pubspec.yam ...

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

    一维码由一组规则排列的黑色线条.白色线条以及对应的字符组成.对倾斜的(没有严重形变)一维码的角度校正,可以根据其黑白相间.排列规则的特点,计算傅里叶频谱,通过傅里叶频谱中直线的倾斜角度计算空间域图像一 ...

  3. winform 扫码识别二维码

    因为公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能. 我根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好) 现在将调用摄像头+识别二 ...

  4. Opencv+Zbar二维码识别(标准条形码/二维码识别)

    使用Opencv+Zbar组合可以很容易的识别图片中的二维码,特别是标准的二维码,这里标准指的是二维码成像清晰,图片中二维码的空间占比在40%~100%之间,这样标准的图片,Zbar识别起来很容易,不 ...

  5. 配置zbar识别二维码(转载)

    原文地址:http://blog.csdn.net/dcrmg/article/details/52108258  二维码解码器Zbar+VS2012开发环境配置 Zbar条码解码器是一个开源的二维码 ...

  6. 基于opencv+python的二维码识别

    花了2天时间终于把二维码识别做出来了,不过效果一般,后面会应用在ROS辅助定位上,废话少说先上图: 具体过程参考了这位大神的博客:http://blog.csdn.net/qq_25491201/ar ...

  7. tornado zbar 二维码识别 ,配合nginx 反向代理,supervisord 监控

    tornado zbar 二维码识别 ,配合nginx 反向代理,supervisord 监控 1.zbar识别二维码程序,python2.6.6 #!/usr/bin/env python # co ...

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

    项目复盘总结 开发需求: 在桌面机器人(向下俯视)摄像头拍摄到的图像中做条形码识别与二维码识别. 条形码在图像固定位置,二维码做成卡片的形式在固定区域内随意摆放. 开发环境及相关库:ubuntu 18 ...

  9. [opencv]二维码识别率提升方案-resize调整

    这里采用循环resize的方式,对二维码图像进行放缩. 识别到name(二维码结果)不为空,则立即退出循环 //循环识别 for (int i = 1;name.empty(); i++){ resi ...

随机推荐

  1. 零基础入门学习Python(31)--永久存储:腌制一缸美味的泡菜

    知识点 pickle( 泡菜 ) 模块介绍: pickle模块作用是持久化的储存数据. 在Python程序运行中得到了一些字符串.列表.字典等数据,想要长久的保存下来,方便以后使用, 而不是简单的放入 ...

  2. 零基础入门学习Python(16)--序列!序列!

    前言 你可能发现了,小甲鱼把这个列表,元组,字符串放在一起讲是有道理的,它们有许多共同点: 都可以通过索引得到每一个元素 默认索引值总是从0开始 可以通过分片的方法得到一个范围内的元素的集合 有很多共 ...

  3. navicat连接mysql8报错,错误提示为1251,原因及解决步骤

    一.错误原因: MySQL8.0版本的加密方式和MySQL5.0的不一样,连接会报错. 二.解决步骤: 1.在linux虚拟机上登录mysql 2.更改加密方式: ALTER USER 'root'@ ...

  4. python 项目部署virtualenv

    安装virtualenv---------------------------------------- mac: pip3 install virtualenv ubuntu: apt instal ...

  5. hdu 4948 Kingdom(推论)

    hdu 4948 Kingdom(推论) 传送门 题意: 题目问从一个城市u到一个新的城市v的必要条件是存在 以下两种路径之一 u --> v u --> w -->v 询问任意一种 ...

  6. 文件 jq 传到后台

    XMLHttpRequest Level 2 添加了一个新的接口——FormData.与普通的 Ajax 相比,使用 FormData 的最大优点就是我们可以异步上传二进制文件. jQuery 2.0 ...

  7. github some rank

    github some rank http://githubrank.com/

  8. 全文搜索(A-3)-用户建模

    用户模型可以分为静态模型.动态模型.混合推荐用户模型. 静态模型往往通过显式方式收集用户偏好信息: 动态模型通过隐式方式收集用户偏好信息: 基于内容的用户系统的推荐模型: 关键字匹配,空间向量模型 协 ...

  9. hdu 1698区间延迟更新

    #include<stdio.h> #define N 100100 struct node { int x,y,yanchi; }a[N*4];//注意数组范围 void build(i ...

  10. bat初学

    今天在重置某工具软件试用期时(汗,盗版可耻=_=!,鄙视自己一下),实在懒得每次过了试用期再点开注册表,手工删除了,就想着写个脚本执行一下,这里就想起来了bat文件. 首先介绍一下for循环,从百度知 ...