二维码定位识别开源的方法,测试两个opencv 和Zbar ,opencv 效果还有很大的提升空间,尤其是普通监控复杂背景下基本上就定位不到二维码,简单分析原因是在整张图上二值化后二维码被吃掉了,处理时间也比较长,我的笔记本要500毫秒以上;Zbar 效果很好720P视频基本可以达到实时分析要求,耗时200毫秒左右。Zbar 中遇到一个坑是github 下载的vs 工程自己编译的64位库使用的时候遇到某些视频帧时报错,仓库中编译好的dll则没有问题。
Zbar Github 地址: https://github.com/noselhq/ZBarWin64
话不多说上代码
定位方法缺陷是默认二维码是水平垂直的,想定位倾斜二维码自动忽略,再找方法吧!!!
int main2()
{
clock_t start = clock(); // 记录程序开始时间,用于计算扫描二维码耗时
zbar::ImageScanner scanner;
scanner.set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
Mat imgOrigin = imread("C:\\Users\\hwx\\Pictures\\QQplayerPic\\2.png"); // 二维码图片相对路径
Mat imgGray;
cvtColor(imgOrigin, imgGray, CV_BGR2GRAY); // 灰度化
int width = imgGray.cols;
int height = imgGray.rows;
Image image(width, height, "Y800", imgGray.data, width * height); // 图片格式转换
scanner.scan(image);
Image::SymbolIterator symbol = image.symbol_begin();
if (image.symbol_begin() == image.symbol_end())
{
cout << "查询条码失败,请检查图片!" << endl;
}
for (; symbol != image.symbol_end(); ++symbol)
{
cout << "类型:" << endl << symbol->get_type_name() << endl << endl;
cout << "条码:" << endl << symbol->get_data() << endl << endl;
cout << "x:" << symbol->get_location_x(0) << endl << endl;
cout << "y:" << symbol->get_location_y(0) << endl << endl;
//定位信息,
int x = symbol->get_location_x(0);
int y = symbol->get_location_y(0);
//根据zbar 返回的多边形的像素点位置 计算宽高
//默认二维码是垂直水平的
int min_x = 0, min_y=0, max_x=0, max_y=0;
Symbol::PointIterator pt = symbol->point_begin();
Symbol::Point p = *pt;
min_x = p.x;
min_y = p.y;
max_x = p.x;
max_y = p.y;
for (; pt != (Symbol::PointIterator)symbol->point_end(); ++pt) {
p = *pt;
min_x = min_x < p.x ? min_x : p.x;
max_x = min_x > p.x ? max_x : p.x;
min_y = min_y < p.y ? min_y : p.y;
max_y = max_y > p.y ? max_y : p.y;
}
cout << "width:" << max_x - min_x << endl << endl;
cout << "height:" << max_y - min_y << endl << endl;
cv::Rect r(x,y, max_x - min_x, max_y - min_y);
cv::rectangle(imgOrigin, r, Scalar(255, 0, 0), 8, LINE_8, 0);
}
image.set_data(nullptr, 0);
clock_t finish = clock(); // 记录程序结束时间
double time_length = (double)(finish - start) / CLOCKS_PER_SEC; //根据两个时刻的差,计算出扫描的时间
cout << "扫描耗时 " << time_length << " seconds." << endl;
imshow("原图", imgOrigin);
waitKey();
return 0;
}
运行结构结构直接框出二维码位置宽高