【学习opencv】opencv条行码检测

条形码检测(简单背景)

利用opencv来识别条形码,首先了解条形码的基本知识

条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。

分析:

识别条形码与车牌类似,检测出图片中的垂直边缘并进行开操作从而形成联通区域,再进行腐蚀膨胀处理以便对条形码位置有更精准的定位。车牌识别可以根据长宽比来筛选,而条形码有不同规格则条形码长宽比不能成为筛选条件,而针对简单背景下的条形码,进行正确的图片处理操作后,最大的轮廓即为条形码区域。

思路:

  • 读入图片并调整大小,以便处理不同的图片
  • 对图片滤波,采用高斯滤波函数GaussianBlur
  GaussianBlur(src,dst,Size(7,7),0);

根据不同需要可选用不同的内核大小,高斯滤波支持多通道单通道图片的输入,为sobel算子做准备

  • 灰度化图片
  • Sobel算子检测边缘
void Sobel(InputArray src, 
OutputArray dst, 
int ddepth, 
int dx, 
int dy, 
int ksize=3, 
double scale=1,
double delta=0, 
int borderType=BORDER_DEFAULT ) 

第三个参数的意思为输出图像的深度,ddepth =-1时,代表输出图像与输入图像相同的深度。
dx=1,dy=0,表示计算X方向的导数,检测出的是垂直方向上的边缘.
dx=0,dy=1,表示计算Y方向的导数,检测出的是水平方向上的边缘.
当sobel算子ksize=3时选用Scharr效果更好。

下图说明了当dx=1,dy=0时检测的垂直边缘

2.下列代码为垂直边缘图减去水平边缘图,可以得到高垂直边缘的图片,滤掉水平边缘的干扰。

    Sobel(img, ximg, CV_8UC1, 1, 0);
    Sobel(img,yimg,CV_8UC1,0,1);
    absdiff(ximg,yimg,res);
  • 二值化图片,可选取较高阈值滤掉像素低的点,而原图是高垂直梯度所以可以保留垂直边缘而又过滤掉干扰因素。

  • 开操作,腐蚀膨胀处理

    形态学操作的对象是二值化图像.有名的形态学操作中包括腐蚀,膨胀,开操作,闭操作等。其中腐蚀,膨胀是许多形态学操作的基础。

这里首先进行开操作,开操作选取宽度大于长度的结构元素,滤掉明显干扰。然后进行腐蚀膨胀操作,消除条形码区的小斑点,腐蚀操作将会腐蚀图像中白色像素,以此来消除小斑点,而膨胀操作将使剩余的白色像素扩张并重新增长回去。

通过图片说明,左图是只进行开操作后结果不正确,定位错误,进行了一系列的腐蚀膨胀操作后,定位精准。

  • 取轮廓并找出包围轮廓最大面积的矩形,即为条形码区.

部分结果图:

代码:

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

int main()
{
    Mat src = imread("pic\\timg7.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);


    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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值