博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Opencv+Zbar二维码识别(一维码校正)
阅读量:4965 次
发布时间:2019-06-12

本文共 2915 字,大约阅读时间需要 9 分钟。

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

先贴出来待校正的一维码和其傅里叶频谱图:

         

傅里叶频谱中亮度值代表了频率变化的强弱,直线的方向代表了频率变化的方向。上图傅里叶频谱中最亮的那条线就是与一维码黑白相间条纹相垂直的方向,找到这条线的角度,就可以计算出一维码的校正角度。

校正步骤:

1. 计算图像X,Y方向上梯度图像,并求和,突出图像边缘信息

2. 离散傅里叶变换,画出一维码的频谱图

3. 霍夫变换定位到傅里叶频谱图中直线,获得直线角度

4. 计算一维码需校正角度,通过仿射变换,校正图像

X、Y方向梯度和:

傅里叶频谱:

阈值化,保留频率变化最明显的分量:

Hough直线定位:

一维码角度校正:

Zbar识别:

Code 实现:

#include "core/core.hpp"    #include "highgui/highgui.hpp"    #include "imgproc/imgproc.hpp"    #include "iostream"  #include "zbar.h"using namespace std; using namespace zbar;using namespace cv;    int main(int argc,char *argv[])    {    	Mat image,imageGray,imageGuussian;    	Mat imageSobelX,imageSobelY,imageSobelOut;    	imageGray=imread(argv[1],0);	imageGray.copyTo(image);	imshow("Source Image",image);	GaussianBlur(imageGray,imageGuussian,Size(3,3),0);   	//水平和垂直方向灰度图像的梯度和,使用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("XY方向梯度和",imageSobelOut);       	Mat srcImg =imageSobelOut;  	    	//宽高扩充,非必须,特定的宽高可以提高傅里叶运算效率  	Mat padded;  	int opWidth = getOptimalDFTSize(srcImg.rows);  	int opHeight = getOptimalDFTSize(srcImg.cols);  	copyMakeBorder(srcImg, padded, 0, opWidth-srcImg.rows, 0, opHeight-srcImg.cols, BORDER_CONSTANT, Scalar::all(0));   	Mat planes[] = {Mat_
(padded), Mat::zeros(padded.size(), CV_32F)}; Mat comImg; //通道融合,融合成一个2通道的图像 merge(planes,2,comImg); dft(comImg, comImg); split(comImg, planes); magnitude(planes[0], planes[1], planes[0]); Mat magMat = planes[0]; magMat += Scalar::all(1); log(magMat, magMat); //对数变换,方便显示 magMat = magMat(Rect(0, 0, magMat.cols & -2, magMat.rows & -2)); //以下把傅里叶频谱图的四个角落移动到图像中心 int cx = magMat.cols/2; int cy = magMat.rows/2; Mat q0(magMat, Rect(0, 0, cx, cy)); Mat q1(magMat, Rect(0, cy, cx, cy)); Mat q2(magMat, Rect(cx, cy, cx, cy)); Mat q3(magMat, Rect(cx, 0, cx, cy)); Mat tmp; q0.copyTo(tmp); q2.copyTo(q0); tmp.copyTo(q2); q1.copyTo(tmp); q3.copyTo(q1); tmp.copyTo(q3); normalize(magMat, magMat, 0, 1, CV_MINMAX); Mat magImg(magMat.size(), CV_8UC1); magMat.convertTo(magImg,CV_8UC1,255,0); imshow("傅里叶频谱", magImg); //HoughLines查找傅里叶频谱的直线,该直线跟原图的一维码方向相互垂直 threshold(magImg,magImg,180,255,CV_THRESH_BINARY); imshow("二值化", magImg); vector
lines; float pi180 = (float)CV_PI/180; Mat linImg(magImg.size(),CV_8UC3); HoughLines(magImg,lines,1,pi180,100,0,0); int numLines = lines.size(); float theta; for(int l=0; l
get_type_name()<
<
get_data()<
<

转载于:https://www.cnblogs.com/mtcnn/p/9411991.html

你可能感兴趣的文章
restframework CBV试图的4种方式
查看>>
大图居中,以1920px为例
查看>>
[C陷阱和缺陷] 第7章 可移植性缺陷
查看>>
linux中configure文件默认执行结果所在位置
查看>>
Windows向Linux上传文件夹
查看>>
20180104-高级特性-Slice
查看>>
6个SQL Server 2005性能优化工具介绍
查看>>
nginx启动、关闭命令、重启nginx报错open() "/var/run/nginx/nginx.pid" failed
查看>>
BZOJ 3097 Hash Killer I
查看>>
UINavigationController的视图层理关系
查看>>
html阴影效果怎么做,css 内阴影怎么做
查看>>
宏观经济
查看>>
综合练习:词频统计
查看>>
BZOJ1026: [SCOI2009]windy数
查看>>
样板操作数
查看>>
64位UBUNTU下安装adobe reader后无法启动
查看>>
组件:slot插槽
查看>>
走进C++程序世界------异常处理
查看>>
Nginx配置文件nginx.conf中文详解(转)
查看>>
POJ 1308 Is It A Tree?(并查集)
查看>>