zbar是一种条码的识别开源库,可以识别很多类型的条码,今天介绍在Windows下使用zbar和opencv实现条码的识别。
第一步:下载安装zbar for Windows(这个只支持Windows32位),或者你比较懒得的话,可以点击这里下载我已经打包好的支持Windows32位和64位2个版本的zbar。Windows下载后的是一个exe文件,点击运行即可,当然,如果你是码农要基于它开发的话,请在安装过程中勾选下面的选项,如下图:
安装好之后你就可以用啦,里面提供了两个小demo,图片条码识别和相机实时条码识别,可以运行玩玩。如下图所示:
如果你要集成该功能到你的项目中的话,就要基于它的库开发了。安装之后,和一些开源库一样,在其根目录下有其lib和bin文件,还有sample供参考,屁话就不多说了。
第二步:在你的IDE上配置好开发环境,这个太简单略过。
第三步:写代码测试。在sample中提供的demo还依赖另一个图像处理库Magick++,主要功能就是将彩色图转为灰度图,但是这里我们使用的opencv来实现的,所以改了他的demo重新实现了该功能。上代码:
以下是官方的demo实现本地图片的条码识别代码(zbar+Magick++)
#include <iostream>
#include <Magick++.h>
#include <zbar.h>
#define STR(s) #s
using namespace std;
using namespace zbar;
int main (int argc, char **argv)
{
if(argc < 2) return(1);
#ifdef MAGICK_HOME
// http://www.imagemagick.org/Magick++/
// under Windows it is necessary to initialize the ImageMagick
// library prior to using the Magick++ library
Magick::InitializeMagick(MAGICK_HOME);
#endif
// create a reader
ImageScanner scanner;
// configure the reader
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
// obtain image data
Magick::Image magick(argv[1]); // read an image file
int width = magick.columns(); // extract dimensions
int height = magick.rows();
Magick::Blob blob; // extract the raw data
magick.modifyImage();
magick.write(&blob, "GRAY", 8);
const void *raw = blob.data();
// wrap image data
Image image(width, height, "Y800", raw, width * height);
// scan the image for barcodes
int n = scanner.scan(image);
// extract results
for(Image::SymbolIterator symbol = image.symbol_begin();
symbol != image.symbol_end();
++symbol) {
// do something useful with results
cout << "decoded " << symbol->get_type_name()
<< " symbol \"" << symbol->get_data() << '"' << endl;
}
// clean up
image.set_data(NULL, 0);
return(0);
}
以下是我修改官方demo实现的条码识别,封装成了函数bool barCodeRecognizeUseZBar(cv::Mat f, std::string &decodedFmt, std::string &symbolData)(zbar+opencv)
bool barCodeRecognizeUseZBar(cv::Mat f, std::string &decodedFmt, std::string &symbolData){
if (f.empty()) return false;
cv::Mat gray;
if (f.channels() == 1) gray = f;
else if (f.channels() == 3) cv::cvtColor(f, gray, CV_RGB2GRAY);
int width = gray.cols;
int height = gray.rows;
// create a reader
zbar::ImageScanner scanner;
// configure the reader
scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
unsigned char *pdata = (unsigned char *)gray.data;
zbar::Image imageZbar(width, height, "Y800", pdata, width * height);
int n = scanner.scan(imageZbar);
if (n > 0){
// extract results
for (zbar::Image::SymbolIterator symbol = imageZbar.symbol_begin();
symbol != imageZbar.symbol_end();
++symbol) {
// do something useful with results
decodedFmt = symbol->get_type_name();
symbolData = symbol->get_data();
}
}else{
return false;
}
// clean up
imageZbar.set_data(NULL, 0);
return true;
}
参数说明:
cv::Mat f:输入的opencv数据结构的图像
std::string &decodedFmt:输出识别得到的条码格式
std::string &symbolData:输出识别得到的条码数据
返回值:是否识别到条码。
第四步:测试代码运行效果,以下是我用普通的笔记本电脑自带的相机和大恒工业相机测试识别二维码的效果图,还不错!如下所示:
总结:测试的效果挺不错的,zbar也挺好用的。以上是32位版本的,可惜的是我在测试64位版本程序的时候,编译就出错了,因为zbar在安装的时候只提供的是32位的库,官网也没有找到64位的Windows版本的,本来想是不是找到源码自己编译一个64位的库,想想感觉挺麻烦的,于是在网上找了一通,后来在GitHub上找到了64位的库,传送门。
有什么疑问建议,欢迎交流。
注:想在ARM嵌入式Linux上运行zbar实现条码识别参考《ZBar移植到ARM》。