1.要定位首先要检视这种条形码的特点,这种图像在X方向上的梯度肯定很明显,同时,Y方向的梯度就没这么明显,所以第一步,我们应该将图像的灰度图像分别计算梯度,用X方向梯度减去Y方向梯度,这样可以保留X方向特征并且去除Y方向的干扰

2.在定义FILE * fp 之后,fopen的用法是: fp = fopen(filename,"w")。而对于fopen_s来说,还得定义另外一个变量errno_t err,然后err = fopen_s(&fp,filename,"w")。返回值的话,对于fopen来说,打开文件成功的话返回文件指针(赋值给fp),打开失败则返回NULL值;对于fopen_s来说,打开文件成功返回0,失败返回非0。

3.步骤

(1)形态学梯度运算,忽略Y方向梯度,着眼于X方向梯度

(2)图像模糊化,为了便于后期的图像连接

(3)图像求阈值,加速算法处理,并合理使用模糊化的效果

(4)形态学去除黑洞,闭运算

(5)膨胀腐蚀,断开二维码连接

(6)查找轮廓,计算轮廓最大面积,拟合轮廓矩形,得到最终结果



4.代码

#include<iostream>
#include<vector>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;


int main()
{
Mat src = imread("条形码2.jpg", 1);
Mat temp;
resize(src, temp, Size(550, 550));
Mat size;
GaussianBlur(temp, size, Size(7, 7), 0);
//高斯滤波
cvtColor(size, size, CV_BGR2GRAY);


Mat ximg, yimg, simg;
Scharr(size, ximg, CV_8U, 1, 0);
/*imshow("sobel垂直边缘", ximg);*/


Scharr(size, yimg, CV_8U, 0, 1);
absdiff(ximg, yimg, simg);


threshold(simg, simg, 225, 255, CV_THRESH_BINARY);
//threshold(simg,simg,0,255,CV_THRESH_BINARY+CV_THRESH_OTSU);




/*进行闭操作,使条形码连成一个联通区域*/
Mat element = getStructuringElement(MORPH_RECT, Size(23, 3));
morphologyEx(simg, simg, MORPH_CLOSE, element);


Mat element5x5 = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat element3x3 = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat element7x7 = getStructuringElement(MORPH_RECT, Size(7, 7));
erode(simg, simg, element7x7);
erode(simg, simg, element7x7);
erode(simg, simg, element5x5);
/*erode(simg, simg, element3x3);
erode(simg, simg, element3x3);
erode(simg, simg, element3x3);*/
dilate(simg, simg, element3x3);
dilate(simg, simg, element3x3);
dilate(simg, simg, element3x3);
dilate(simg, simg, element3x3);
dilate(simg, simg, element3x3);
dilate(simg, simg, element3x3);
dilate(simg, simg, element3x3);


imshow("sobel垂直边缘", simg);
vector<vector<Point>>contours;
findContours(simg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
/*drawContours(Resize,contours,-1,Scalar(255,0,0),3,8);
找出最大的面积的矩形*/
int flag = 0;
double tem = 0;
for (int i = 0; i < contours.size(); i++)
{


if (tem < fabs(contourArea(contours[i]))) {
tem = fabs(contourArea(contours[i]));
flag = i;
}


}
//画矩形
RotatedRect rect = minAreaRect(contours[flag]);
Point2f vect[4];
rect.points(vect);
for (int i = 0; i < 4; i++)
{
line(temp, vect[i], vect[(i + 1) % 4], Scalar(255, 0, 0), 2, 8);
}
namedWindow("dst", CV_WINDOW_AUTOSIZE);
imshow("dst", temp);
waitKey(0);


return 0;
}

5.运行结果

条形码的识别



相关文章: