本工程是利用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画出Roi区域后转换为ZBar的图像类型进行识别总是会识别出同一排的其他二维码。
出现这种问题的原因是因为在划定Roi区域的时候并不会划定一块新的区域来储存图像,而是指向原来的图像,相当于将原图送到了ZBar进行识别,解决方法是利用copyTo()将划定的Roi区域储存在新的图像变量中。
详细解释:
openCV_C++笔记 : ROI感兴趣区域与Rect类
关于opencv中ROI区域的理解