我想用OPENCV 自带的qrcode识别和ZBar库进行二维码的识别,所用的原图如下(百度上随便找的):
经过二值化,确定角点和变换矩阵,对原图进行透视变换,再截取图片转换成灰度图得到校正后的二维码图片如下:
分别用自带的QRcode算法和ZBar库对直接二值化的图和经过校正之后的灰度图进行识别,下面用QRcode识别的代码,imageSource是灰度图,thresholdQRcode是直接二值化的图。
QRCodeDetector qrcodeDetector;
String information1;
String information2;
vector<Point> points;
bool isQRcode1 = qrcodeDetector.detect(imageSource, points);
if (isQRcode1) {
information1 = qrcodeDetector.detectAndDecode(imageSource, points);
cout << "识别成功:"<< information1 << endl;
}
else {
cout << "未识别成功!!" << endl;
}
bool isQRcode2 = qrcodeDetector.detect(thresholdQRcode, points);
if (isQRcode2) {
information2 = qrcodeDetector.detectAndDecode(thresholdQRcode, points);
cout << "识别成功:" << information2 << endl;
}
else {
cout << "未识别成功!!" << endl;
}
接着再用ZBar进行识别,都是一样的代码,代码如下:
//zbar解码--必须在exe同目录下加入两个dll文件,注意灰度图像!!!
ImageScanner scanner;
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
int width1 = imageSource.cols;
int height1 = imageSource.rows;
uchar *raw1 = (uchar *)imageSource.data;
Image imageZbar1(width1, height1, "Y800", raw1, width1*height1);
scanner.scan(imageZbar1);
Image::SymbolIterator symbol1 = imageZbar1.symbol_begin();
if (imageZbar1.symbol_begin() == imageZbar1.symbol_end()) {
cout << "未识别成功!!" << endl;
}
else {
for (; symbol1 != imageZbar1.symbol_end(); ++symbol1) {
cout << "类型: " << symbol1->get_type_name() << endl;
cout << "条码:" << symbol1->get_data() << endl;
}
}
int width2 = thresholdQRcode.cols;
int height2 = thresholdQRcode.rows;
uchar *raw2 = (uchar *)thresholdQRcode.data;
Image imageZbar2(width2, height2, "Y800", raw2, width2*height2);
scanner.scan(imageZbar2);
Image::SymbolIterator symbol2 = imageZbar2.symbol_begin();
if (imageZbar2.symbol_begin() == imageZbar2.symbol_end()) {
cout << "未识别成功!!" << endl;
}
else {
for (; symbol2 != imageZbar2.symbol_end(); ++symbol2) {
cout << "类型: " << symbol2->get_type_name() << endl;
cout << "条码:" << symbol2->get_data() << endl;
}
}
实验结果如下:
结果表明QRcode都识别出来了,但是ZBar根据校正后的二维码却没有识别出来。我非常奇怪为啥原来直接二值化的图能够识别,我进行处理校正后的图反而识别不出来了??希望有人能解释一下。
接下来我不用灰度图,而是直接用矫正后的原图,没有转变成灰度图直接进行识别,结果如下:
出现了新的错误,同样没有识别成功,有没有人说说这错误是什么意思?
然后我对直接二值化的图像进行透视变换截取,得到矫正后的二值化图象来直接进行识别,图像如下:
结果如下:
现在结果完全倒过来了,QRcode对矫正后的图片识别不了,反而ZBar识别成功了,这到底是为啥?或者说有什么更进一步的手段能够提高识别的成功率?
识别的连接:
https://blog.csdn.net/fangyan90617/article/details/80504838
提高准确度的话可以用zxing。
//图片像素按比例缩放
Image imagePic = Image.FromStream(stream);
Bitmap bmp = imagePic as Bitmap;
if (imagePic.Width > 512)
{
int zoomMultiple = imagePic.Width / 512;
int toWidth = 512;
int toHeight = imagePic.Height / zoomMultiple;
bmp = new Bitmap(toWidth, toHeight);
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.Clear(Color.Transparent);
g.DrawImage(imagePic,
new Rectangle(0, 0, toWidth, toHeight),
new Rectangle(0, 0, imagePic.Width, imagePic.Height),
GraphicsUnit.Pixel);
imagePic.Dispose();
}
//第一种识别方式Zxing
var codes = new BarcodeReader
{
AutoRotate = true,
TryInverted = true,
Options = new DecodingOptions
{
TryHarder = true
}
}.DecodeMultiple(bmp);
if (codes != null)
{
result.DataView = codes[0].Text;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
//第二种识别方式ZBar
using (ZBar.ImageScanner scanner = new ZBar.ImageScanner())
{
var symbols = scanner.Scan(bmp);
if (symbols.Count > 0 && symbols[0].Data.Length > 8)
{
result.DataView = symbols[0].Data;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
}
//第三种识别方式Zxing
MultiFormatReader reader = new MultiFormatReader();
Dictionary<DecodeHintType, object> dictionary = new Dictionary<DecodeHintType, object> { { DecodeHintType.CHARACTER_SET, "UTF-8" } };
RGBLuminanceSource source = new RGBLuminanceSource(QrCode.Bitmap2Rgb(bmp), bmp.Width, bmp.Height);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result resultVerify = reader.decode(bitmap, dictionary);
if (resultVerify != null)
{
result.DataView = resultVerify.Text;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
string thoughtWorksResult = "";
//第四种识别方式thoughtWorks
try
{
QRCodeDecoder decoder = new QRCodeDecoder();
thoughtWorksResult = decoder.decode(new ThoughtWorks.QRCode.Codec.Data.QRCodeBitmapImage(bmp));
}
catch (Exception)
{
}
if (!string.IsNullOrEmpty(thoughtWorksResult))
{
result.DataView = thoughtWorksResult;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
else
{
result.Code = Enum.ResultCode.DealFail;
result.Message = "识别失败";
}
//图片像素按比例缩放
Image imagePic = Image.FromStream(stream);
Bitmap bmp = imagePic as Bitmap;
if (imagePic.Width > 512)
{
int zoomMultiple = imagePic.Width / 512;
int toWidth = 512;
int toHeight = imagePic.Height / zoomMultiple;
bmp = new Bitmap(toWidth, toHeight);
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.Clear(Color.Transparent);
g.DrawImage(imagePic,
new Rectangle(0, 0, toWidth, toHeight),
new Rectangle(0, 0, imagePic.Width, imagePic.Height),
GraphicsUnit.Pixel);
imagePic.Dispose();
}
//第一种识别方式Zxing
var codes = new BarcodeReader
{
AutoRotate = true,
TryInverted = true,
Options = new DecodingOptions
{
TryHarder = true
}
}.DecodeMultiple(bmp);
if (codes != null)
{
result.DataView = codes[0].Text;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
//第二种识别方式ZBar
using (ZBar.ImageScanner scanner = new ZBar.ImageScanner())
{
var symbols = scanner.Scan(bmp);
if (symbols.Count > 0 && symbols[0].Data.Length > 8)
{
result.DataView = symbols[0].Data;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
}
//第三种识别方式Zxing
MultiFormatReader reader = new MultiFormatReader();
Dictionary<DecodeHintType, object> dictionary = new Dictionary<DecodeHintType, object> { { DecodeHintType.CHARACTER_SET, "UTF-8" } };
RGBLuminanceSource source = new RGBLuminanceSource(QrCode.Bitmap2Rgb(bmp), bmp.Width, bmp.Height);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result resultVerify = reader.decode(bitmap, dictionary);
if (resultVerify != null)
{
result.DataView = resultVerify.Text;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
string thoughtWorksResult = "";
//第四种识别方式thoughtWorks
try
{
QRCodeDecoder decoder = new QRCodeDecoder();
thoughtWorksResult = decoder.decode(new ThoughtWorks.QRCode.Codec.Data.QRCodeBitmapImage(bmp));
}
catch (Exception)
{
}
if (!string.IsNullOrEmpty(thoughtWorksResult))
{
result.DataView = thoughtWorksResult;
result.Code = Enum.ResultCode.DealSuccess;
result.Message = "识别成功";
return ReturnResp(result);
}
else
{
result.Code = Enum.ResultCode.DealFail;
result.Message = "识别失败";
}
应该是实现机制不同导致的,用一个就好了哈