zbar+opencv检测图片中的二维码或条形码
zbar本身自带检测二维码条形码功能,这里使用opencv只是做一些简单的读取图片,灰度图片以及显示条形码和二维码时用到一些绘制
// barcode-qrcodescanner.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <opencv2/opencv.hpp> #include <zbar.h> #pragma comment( lib,"winmm.lib" ) using namespace std; typedef struct { string type; string data; vector <cv::Point> location; } decodedObject; // 识别条形码或二维码 void decode(cv::Mat &im, vector<decodedObject>&decodedObjects) { // 创建zbar 扫描检测对象 zbar::ImageScanner scanner; // 配置扫描器 scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); // 图片转为灰度图 cv::Mat imGray; cv::cvtColor(im, imGray, cv::COLOR_BGR2GRAY); // 将图片数据转换为zbar图片对象 zbar::Image image(im.cols, im.rows, "Y800", (uchar *)imGray.data, im.cols * im.rows); // 扫描检测 int n = scanner.scan(image); // 打印检测结果 for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) { decodedObject obj; obj.type = symbol->get_type_name(); obj.data = symbol->get_data(); // 检测到的对象类型和数据 cout << "Type : " << obj.type << endl; cout << "Data : " << obj.data << endl << endl; // 对象所处的位置 for (int i = 0; i < symbol->get_location_size(); i++) { obj.location.push_back(cv::Point(symbol->get_location_x(i), symbol->get_location_y(i))); } decodedObjects.push_back(obj); } } // 显示条形码和二维码在图片中的区域 void display(cv::Mat &im, vector<decodedObject>&decodedObjects) { for (int i = 0; i < decodedObjects.size(); i++) { vector<cv::Point> points = decodedObjects[i].location; vector<cv::Point> hull; if (points.size() > 4) convexHull(points, hull); else hull = points; int n = hull.size(); for (int j = 0; j < n; j++) { cv::line(im, hull[j], hull[(j + 1) % n], cv::Scalar(255, 0, 0), 3); } } // 显示结果 cv::imshow("Results", im); cv::waitKey(0); } int main(int argc, char* argv[]) { // opencv读取图片 cv::Mat im = cv::imread("zbar-test.jpg"); vector<decodedObject> decodedObjects; // 查找二维码或条形码 decode(im, decodedObjects); // 显示位置 display(im, decodedObjects); return EXIT_SUCCESS; }
这里用到zbar所以需要去下载一个zbar库,因为我用的是vs2017并且项目配置的是x64位。这里有个配置好的需要的下载