我在zedboard上跑了zxing和zbar,zbar的实时性确实要比zxing好很多,所以这里记录下zbar移植的过程,方便下次遇到时使用。
1.下载zbar的源码
http://zbar.sourceforge.net/download.html
http://zbar.sourceforge.net/api/zbar_8h.html#f1a98f95d0c058ad356acb73089ec2eb
https://blog.ayoungprogrammer.com/2013/07/tutorial-scanning-barcodes-qr-codes.html/
下载 zbar-0.10.tar.bz2
使用tar -xvf zbar-0.10.tar.bz2 解压
2.在zbar的目录下创建一个tmp的目录,交叉编译zbar
cd zbar-0.10/
mkdir tmp
touch build.sh
vim build.sh
./configure --host=arm-xilinx-linux-gnueabi --without-imagemagick --disable-video --without-qt --without-gtk --without-x --without-python --exec-prefix=$PWD/tmp/install --prefix=$PWD/tmp/install LIBS=-L$PWD/tmp/lib CPPFLAGS=-I$PWD/tmp/include \ CC=arm-xilinx-linux-gnueabi-gcc
chmod +x build.sh
./build.sh --> make --> make install
3.编写应用测试
在tmp的install目录下面将会产生include和lib的目录,里面是头文件和交叉编译出来的libzbar.a的静态库和动态库。
把交叉编译出来的动态库libzbar.so.0.2.0拷贝到zedboard的/usr/lib目录下,然后在/usr/lib目录下创建一个软连接,命令:
ln -s /usr/lib/libzbar.so.0.2.0 /usr/lib/libzbar.so.0
编写应用程序:
#include <opencv2/opencv.hpp> #include <iostream> #include <stdio.h> #include "zbar.h" int main(int argc, char** argv){ if(argc < 2){ std::cout << "Usage: ./test_zbar barcode.png" << std::endl; return -1; } cv::Mat src = cv::imread(argv[1], 1); cv::Mat gray; if (src.channels() == 1) gray = src; else cv::cvtColor(src, 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 std::string decodedFmt = symbol->get_type_name(); std::string symbolData = symbol->get_data(); cv::putText(src, decodedFmt, cv::Point(10, 20), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(255, 0, 0), 1); cv::putText(src, symbolData, cv::Point(10, 60), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(255, 0, 0), 1); std::cout << decodedFmt << std::endl; std::cout << symbolData << std::endl; } }else{ char error_str[64]; sprintf(error_str, "Not got a barcode!"); cv::putText(src, error_str, cv::Point(10, 20), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0, 0, 255), 1); std::cout << "Not got a barcode!" << std::endl; } cv::imwrite("result.png", src); // clean up imageZbar.set_data(NULL, 0); }
Makefile文件如下:
# vdma test # Author: liangchunjiang # Date: 2018.03.29 INCLUDE = -I/home/lchj/zedboard/tools/opencv-2.4.9/install/include -I/home/lchj/zedboard/Mt9p034_Project/zbar_app/include LIBS = -L/home/lchj/zedboard/tools/opencv-2.4.9/install/lib -L/home/lchj/zedboard/Mt9p034_Project/zbar_app/lib LINKS = -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann -lzbar PTHREAD = -lpthread -lrt all: arm-xilinx-linux-gnueabi-g++ -o zbar_main main.cpp ${INCLUDE} ${LIBS} ${LINKS} clean: rm -rf zbar_main
#include "zbar.h" #include "cv.h" #include "highgui.h" #include <iostream> using namespace std; using namespace zbar; using namespace cv; int main(void){ ImageScanner scanner; scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1); // obtain image data char file[256]; cin>>file; Mat img = imread(file,0); Mat imgout; cvtColor(img,imgout,CV_GRAY2RGB); int width = img.cols; int height = img.rows; uchar *raw = (uchar *)img.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) { vector<Point> vp; // do something useful with results cout << "decoded " << symbol->get_type_name() << " symbol "" << symbol->get_data() << '"' <<" "<< endl; int n = symbol->get_location_size(); for(int i=0;i<n;i++){ vp.push_back(Point(symbol->get_location_x(i),symbol->get_location_y(i))); } RotatedRect r = minAreaRect(vp); Point2f pts[4]; r.points(pts); for(int i=0;i<4;i++){ line(imgout,pts[i],pts[(i+1)%4],Scalar(255,0,0),3); } cout<<"Angle: "<<r.angle<<endl; } imshow("imgout.jpg",imgout); // clean up image.set_data(NULL, 0); waitKey(); }