【图像处理】条形码与二维码的定位与识别

代码实现简单环境下的条形码与二维码的定位与识别:

原图:

#include<iostream>
#include<opencv2\opencv.hpp>
#include<zbar.h>

using namespace std;
using namespace cv;
using namespace zbar;

//寻找最大的轮廓
static vector<cv::Point> FindBiggestContour(Mat src)
{
	int imax = 0; //代表最大轮廓的序号
	int imaxcontour = -1; //代表最大轮廓的大小
	std::vector<std::vector<cv::Point>>contours;
	findContours(src, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
	for (int i = 0; i<contours.size(); i++)
	{
		int itmp = contourArea(contours[i]);//这里采用的是轮廓大小
		if (imaxcontour < itmp)
		{
			imax = i;
			imaxcontour = itmp;
		}
	}
	return contours[imax];
}

//获取二维码
void detect_decode_qrcode()
{
	Mat img = imread("barcode_qrcode.jpg");
	if (img.empty())
	{
		cout << "reading images fails" << endl;
	}
	//灰度化
	Mat img_gray, img_bin;
	cvtColor(img, img_gray, COLOR_BGR2GRAY);
	threshold(img_gray, img_bin, 100, 255, THRESH_OTSU | THRESH_BINARY_INV);  //THRESH_BINARY_INV  二值化取反						 
	vector<vector<Point>> contours, contours2; //找轮廓  找到的轮廓按照树的方式排列
	vector<Vec4i> hierarchy;
	findContours(img_bin, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE);
	int c = 0, ic = 0, area = 0;
	int parentIdx = -1;
	for (int i = 0; i < contours.size(); i++)
	{											//遍历所有的大轮廓									
		if (hierarchy[i][2] != -1 && ic == 0)  //如果 这个大轮廓没有父轮廓 hierarchy[i][2] != -1 说明他是存在子轮廓的
		{
			parentIdx = i;
			ic++;
		}
		else if (hierarchy[i][2] != -1)
		{
			ic++;
		}
		//最外面的清0
		else if (hierarchy[i][2] == -1)
		{
			ic = 0;
			parentIdx = -1;
		}
		//找到定位点信息
		if (ic == 2)
		{
			contours2.push_back(contours[parentIdx]);
			ic = 0;
			parentIdx = -1;
		}
	}
	//二维码中间是应该有三个特征轮廓的,如果等于3 那么就认为它是有二维码的
	if (contours2.size() != 3)
	{
		printf("finding 3 rects fails \n");
	}
	//把二维码最外面的轮廓构造成一个新的点集
	Rect new_rect;
	vector<Point> all_points;
	for (int i = 0; i < contours2.size(); i++)
	{
		for (int j = 0; j < contours2[i].size(); j++)
			all_points.push_back(contours2[i][j]);
	}
	new_rect = boundingRect(all_points);  //根据二维码构成得点集,找到一个最小的外包所有点集 的矩形
										  //  Rect rect(230, 5, 280, 290);//左上坐标(x,y)和矩形的长(x)宽(y)
										  //  cv::rectangle(src, rect, Scalar(255, 0, 0),1, LINE_8,0);
	rectangle(img, new_rect, Scalar(0, 0, 255), 8, 0);
	Mat result_img = img_gray(new_rect);   //将找到的矩形 放进灰度图中,这样图片就可以根据矩形切割出来了
	ImageScanner scanner;
	scanner.set_config(ZBAR_QRCODE, ZBAR_CFG_ENABLE, 1);
	int width = result_img.step;  //因为这一小部分是截取出来的
	int height = result_img.rows;
	uchar *raw = (uchar *)result_img.data;
	Image imageZbar(width, height, "Y800", raw, width * height);
	scanner.scan(imageZbar);
	Image::SymbolIterator symbol = imageZbar.symbol_begin();
	if (imageZbar.symbol_begin() == imageZbar.symbol_end())
	{
		cout << "查询二维码失败,请检查图片!" << endl;
	}
	for (; symbol != imageZbar.symbol_end(); ++symbol)
	{
		cout << "类型:" << endl << symbol->get_type_name() << endl << endl;
		cout << "二维码:" << endl << symbol->get_data() << endl << endl;
	}
	imageZbar.set_data(NULL, 0);
	//imshow("mat",img);
	imshow("mat1", result_img);
}


//获取条形码
void detect_decode_barcode()
{
	Mat src = imread("barcode_qrcode.jpg");
	if (src.empty())
	{
		cout << "reading images fails" << endl;
	}
	Mat sobel;
	Mat canny;
	Mat canny_output;
	//1、//灰度化
	Mat gray;
	cvtColor(src, gray, COLOR_BGR2GRAY); 
	//2、二值化
	//Canny(gray, canny, 100, 255);
	Mat bin;
	threshold(gray, bin, 0, 255, THRESH_OTSU | THRESH_BINARY_INV);
	//3、形态学滤波
	Mat element = getStructuringElement(MORPH_ELLIPSE, Size(12, 2));
	morphologyEx(bin, bin, MORPH_DILATE, element); //形态学滤波  找到条形码 大白
	//morphologyEx(canny, canny, MORPH_ERODE, element);
	//4、寻找最大的轮廓
	Rect boundRect = boundingRect(Mat(FindBiggestContour(bin)));
	Mat result_img = gray(boundRect);
	imshow("mat2", result_img);

	ImageScanner scanner;
	scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
	int width = result_img.step;
	int height = result_img.rows;
	uchar *raw = (uchar *)result_img.data;
	Image imageZbar(width, height, "Y800", raw, width * height);
	scanner.scan(imageZbar); //扫描条码      
	Image::SymbolIterator symbol = imageZbar.symbol_begin();
	if (imageZbar.symbol_begin() == imageZbar.symbol_end())
	{
		cout << "查询条码失败,请检查图片!" << endl;
	}
	for (; symbol != imageZbar.symbol_end(); ++symbol)
	{
		cout << "类型:" << endl << symbol->get_type_name() << endl << endl;
		cout << "条码:" << endl << symbol->get_data() << endl << endl;
	}
	imageZbar.set_data(NULL, 0);
}
//主函数
int main()
{
	detect_decode_qrcode(); 
	detect_decode_barcode();
	waitKey(0);
	return 0;
}

 

 

检测结果图:

调用Zbar库函数,识别分割出来的二维码与条形码

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值