基于ZBar做二维码识别,识别率很低,为了提高识别率,可以先将图像进行灰度化处理再进行识别,准确率将会有很大提升。
#include <vector>
#include <algorithm>
#include <string>
#include <math.h>
#include <iostream>
#include<map>
#include <cv.h>
#include <highgui.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#ifdef _DEBUG
#pragma comment(lib, "opencv_world300d.lib")
#else
#pragma comment(lib, "opencv_world300.lib")
#endif
#include <zbar.h>
using namespace zbar;
#pragma comment(lib, "libzbar-0.lib")
using namespace cv;
using namespace std;
namespace QRCode{
std::string GetQRInBinImg(Mat binImg);
std::string ZbarDecoder(Mat img);
//对二值图像进行识别,如果失败则开运算进行二次识别
std::string GetQR(Mat img)
{
Mat binImg;
Mat adaptiveImg;
double thre = threshold(img, binImg, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);//threshold 第一个参数即原图像必须为灰度图
std::string result;
result = GetQRInBinImg(binImg);
if(result.empty())//如果阈值otsuthreshold失败,则采用高斯自适应阈值化,可以识别出一定的控制阈值也识别不出来的二维码
{
cv::adaptiveThreshold(img, adaptiveImg, 255, ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 33, 0);//threshold第一个参数即原图像必须为灰度图,最佳33
result = GetQRInBinImg(adaptiveImg);
}
thre = thre/2;//ostu和自适应阈值都失败,将从ostu阈值的一般开始控制阈值不断增长
while (result.empty() && thre<255)
{
threshold(img, binImg, thre, 255, cv::THRESH_BINARY);
result = GetQRInBinImg(binImg);
thre += 5;//阈值步长设为5,步长越大,识别率越低,速度越快,对于当前测试图片的情况为5识别出来的最多
}
return result;
}
//主体函数
std::string GetQRInBinImg(Mat binImg)
{
std::string result = ZbarDecoder(binImg);
if (result.empty())
{
Mat openImg;
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(binImg, openImg, MORPH_OPEN, element);
result = ZbarDecoder(openImg);
}
return result;
}
//zbar接口
std::string ZbarDecoder(Mat img)
{
float point[8];
string result;
std::string res;
ImageScanner scanner;
const void *raw = (&img)->data;
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
Image image(img.cols, img.rows, "Y800", raw, img.cols * img.rows);
int n = scanner.scan(image);
Image::SymbolIterator symbol = image.symbol_begin();
res = image.symbol_begin()->get_data();
cout << res.c_str() << endl;
image.set_data(NULL, 0);
return res;
}
}
调用示例:
cv::Mat src = cv::imread(lpszFileName);
Mat imageGray;
cvtColor(src, imageGray, CV_RGB2GRAY);
string ret = QRCode::GetQR(imageGray);
if ( !ret.empty() )
{
TRACE("图片%s...识别结果=[%s]\n", lpszFileName, ret.c_str());
}
else
{
TRACE("图片%s...[%s]\n", lpszFileName, "未识别");
}