使用OpenCV+ZBar实现多条形码识别

本工程是利用OpenCV4.5.4进行图像预处理,将条形码找到并送进ZBar进行识别
目前能实现对干扰少的多条形码图片进行是被,后期希望能够利用摄像头在有干扰的情况下对条形码进行识别

工程代码

#include 
#include 
#include 
using namespace std;
using namespace cv;
using namespace zbar;
int main()
{
	ImageScanner scanner;
	//后期将会改用摄像头识别
	//VideoCapture cap(0);
	//if (!cap.isOpened())  //检查是否打开摄像头
	//	return -1;
	while (1)
	{
		Mat image_s, image_gray, image_gradX, image_gradY, image_grad;
		image_s = imread("多条形码.jpg", 1);//读取照片
		//cap >> image_s;//将相机中的照片保存到新的
		imshow("source", image_s);//显示图片
		cvtColor(image_s, image_gray, COLOR_BGR2GRAY);//转换为灰度图
		imshow("gray", image_gray);
		//分别计算图像在xy方向的导数
		Scharr(image_gray, image_gradX, CV_8U, 1, 0);
		Scharr(image_gray, image_gradY, CV_8U, 0, 1);
		//因为我们的条形码在X方向上,所以减掉y方向的导数
		subtract(image_gradX, image_gradY, image_grad);
		imshow("grad", image_grad);
		Mat image_threshold;
		//对图像进行二值化并进行形态学处理
		threshold(image_grad, image_threshold, 100, 255, THRESH_BINARY);//二值化
		Mat  element = getStructuringElement(1, Size(9, 9));//创建形态学的结构元素
		//膨胀两次,使条形码的二值化图像相连通
		dilate(image_threshold, image_threshold, element);
		dilate(image_threshold, image_threshold, element);
		//腐蚀两次
		erode(image_threshold, image_threshold, element);
		erode(image_threshold, image_threshold, element);
		//去除孤立的点
		morphologyEx(imageSobleOutThreshold, imageSobleOutThreshold, MORPH_CLOSE, element);
		vector<vector<Point>> contours;
		vector<Vec4i> hierarchy;
		findContours(imageSobleOutThreshold, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);//寻找轮廓
		for (int i = 0; i < contours.size(); i++)
		{
			double TempArea = fabs(contourArea(contours[i]));//计算轮廓的面积
			if (TempArea > 1000)//轮廓面积大于1000认为是条形码
			{
				Rect rect = boundingRect(contours[i]);//计算点集的矩形边界
				rectangle(image_s, rect, Scalar(255), 2);//画出矩形
				Mat image_roi = image_gray(rect);//根据轮廓画出Roi区域
				Mat image_scan;
				image_roi.copyTo(image_scan);//将Roi区域的图像复制到新的变量中
				//将OpenCV的图像转换为ZBar的图像
				int width = image_scan.cols;
				int height = image_scan.rows;
				uchar* image_zbar = (uchar*)image_scan.data;
				Image imageZbar(width, height, "Y800", image_zbar, width * height);
				scanner.scan(imageZbar); //扫描条码  
				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("end", image_s);//显示框选了条形码的矩形
		cout << "--------------------" << endl;
		if (waitKey(10) == 'q');
	}
	return 0;
}

运行效果

使用OpenCV+ZBar实现多条形码识别_第1张图片
使用OpenCV+ZBar实现多条形码识别_第2张图片
在编写过程中遇到的最大的问题就是在利用Opencv画出Roi区域后转换为ZBar的图像类型进行识别总是会识别出同一排的其他二维码。
出现这种问题的原因是因为在划定Roi区域的时候并不会划定一块新的区域来储存图像,而是指向原来的图像,相当于将原图送到了ZBar进行识别,解决方法是利用copyTo()将划定的Roi区域储存在新的图像变量中。
详细解释:
openCV_C++笔记 : ROI感兴趣区域与Rect类
关于opencv中ROI区域的理解

你可能感兴趣的:(opencv,计算机视觉,图像处理)