识别条形码,首先我们需要考虑到识别图片的大小以及干扰因素等等。
因此我们需要进行的操作主要有三个部分:
目录
进行以下操作,首先要确保opencv库以及zbar库正常安装。有疑问可以参考笔者关于opencv以及zbar配置的文章
1、图片平滑降噪
首先我们需要使用到以下头文件
#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
#include "zbar.h"
#include "opencv.hpp"
#include <iostream>
还需要声明命名空间
using namespace std;
using namespace cv;
using namespace zbar;
读取图像并进行平滑降噪处理
//读取文件
Mat img = imread("1.jpg")//1.jpg是处在工作目录下的jpg文件名称
Mat imgGrey;
//转化为灰度图,方便运算与识别
cvtColor(img, imgGray, COLOR_RGB2GRAY);
// 高斯平滑滤波
Mat imgGus;
GaussianBlur(imgGray, imgGus, Size(3,3), 0);
//4.求得水平和垂直方向灰度图像的梯度差,使用Sobel算子
Mat imageX16S, imageY16S;
Sobel(imgGus, imageX16S, CV_16S, 1, 0, 3, 1, 0, 4);
Sobel(imgGus, imageY16S, CV_16S, 0, 1, 3, 1, 0, 4);
convertScaleAbs(imageX16S, imageSobelX, 1, 0);
convertScaleAbs(imageY16S, imageSobelY, 1, 0);
imageSobelOut=imageSobelX-imageSobelY;
//5.均值滤波,消除高频噪声
Mat imgBlur;
blur(imageSobelOut, imgBlur, Size(3,3));
//6.二值化
Mat imgThreshold;
threshold(imgBlur,imgThreshold,80,255,THRESH_BINARY);
2、根据目标特征运算
首先、条形码在前面的处理降噪之后,我们需要让其中间的空隙连起来形成一个长方形块,方便对其定位,因此使用闭运算填充条形码间隙
//闭运算,填充条码间隙
Mat element = getStructuringElement(0,Size(7,7));//闭运算需要的参数
morphologyEx(imgThreshold,imgThreshold,MORPH_CLOSE,elementmor);
紧接着,进行腐蚀,去除孤立的点以及线
// 腐蚀,去除孤立的点
Mat elementero1=getStructuringElement(0,Size(60,3));//此处的size()参数要根据图像特征进行调整
erode(imgThreshold,imgThreshold,elementero1);
最后,将剩下的筛选出来的条形码块进行膨胀拓宽,达到符合条形码轮廓的大小
// 膨胀,根据目标条形码的大小,需要多次膨胀操作,具体次数随情况变化
Mat elementdli=getStructuringElement(0,Size(30,7));
dilate(imgThreshold,imgThreshold,elementdli);
dilate(imgThreshold,imgThreshold,elementdli);
dilate(imgThreshold,imgThreshold,elementdli);
dilate(imgThreshold,imgThreshold,elementdli);
dilate(imgThreshold,imgThreshold,elementdli);
3、图片定位与识别
vector<vector<Point>> contours;
vector<Vec4i> hiera;
findContours(imageSobleOutThreshold,contours,hiera,RETR_EXTERNAL,CHAIN_APPROX_NONE);
Mat scanimg[contours.size()];
for(int i=0;i<contours.size();i++)//contours is the contour of my image
{
Rect rect=boundingRect((Mat)contours[i]);//rect is a coordinate,it's has 4
//element
rectangle(image,rect,Scalar(255),2);
cout<<"a"<<endl;
scanimg[i] = image(rect);//image accoding to the rect to cut the pictrue
//process come to here ,things we need do to pictrue is
cvtColor(scanimg[i], scanimg[i], COLOR_RGB2GRAY);
string o = num2str(i);
imshow(o, scanimg[i]);
//already done,the next step is Identify barcode
ImageScanner scanner;
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
int width = scanimg[i].cols;
int height = scanimg[i].rows;
uchar *raw = (uchar *)scanimg[i].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;
}
}
需要完整代码可以留言,有需要笔者会发出来。