c# EmguCv定位二维码

c# EmguCv定位二维码

http://blog.csdn.net/gaobobo138968/article/details/47663607

Emgu 和opencv一样,用opencv写的程序当然也可以“翻译”为Emgu版,这里展示一个demo,使用Emgu定位图片中的二维码。

1.载入图像
System.Drawing.Image img = System.Drawing.Image.FromFile("E:\\code.jpg");
Bitmap barcodeBitmap = new Bitmap(img);
Image<Bgr, byte> img_src = new Image<Bgr, byte>(barcodeBitmap );
2.转为灰度图
Image<Gray, byte> imput_gray = new Image<Gray, byte>(img_src.Size);
CvInvoke.cvCvtColor(img_src, imput_gray, COLOR_CONVERSION.BGR2GRAY);
3.计算x,y方向梯度,相加
        Image<Gray, byte> grad_x1 = new Image<Gray, byte>(img_src.Size); 
        Image<Gray, byte> grad_y1 = new Image<Gray, byte>(img_src.Size);
        Image<Gray, byte> grad_all = new Image<Gray, byte>(img_src.Size);
        CvInvoke.cvSobel(imput_gray, grad_x1, 0, 1,3);
        CvInvoke.cvSobel(imput_gray, grad_y1, 1, 0, 3);
        CvInvoke.cvAdd(grad_x1, grad_y1, grad_all, IntPtr.Zero);

梯度图:
这里写图片描述

4.平均模糊
//平均模糊(9*9内核大小)
CvInvoke.cvSmooth(grad_all, grad_all, SMOOTH_TYPE.CV_BLUR, 9, 9,0,0);
CvInvoke.cvShowImage("平均模糊", grad_all);

平均模糊结果:
这里写图片描述

5.二值化
CvInvoke.cvThreshold(grad_all, grad_all, 100, 255, THRESH.CV_THRESH_BINARY);
CvInvoke.cvShowImage("二值化", grad_all);

二值化图片:
这里写图片描述

6.消除裂缝
StructuringElementEx element = new StructuringElementEx( 21, 21,0, 0, Emgu.CV.CvEnum.CV_ELEMENT_SHAPE.CV_SHAPE_RECT );
CvInvoke.cvMorphologyEx( grad_all, grad_all, IntPtr.Zero, element, CV_MORPH_OP.CV_MOP_CLOSE, 1 );
CvInvoke.cvShowImage("消除裂缝", grad_all);

图片结果:
这里写图片描述

7.膨胀与腐蚀(消除杂点)
StructuringElementEx element1 = new StructuringElementEx(5, 5, 0, 0, Emgu.CV.CvEnum.CV_ELEMENT_SHAPE.CV_SHAPE_RECT);
CvInvoke.cvErode(grad_all, grad_all, element1, 4);
CvInvoke.cvDilate(grad_all, grad_all, element1, 4);
CvInvoke.cvShowImage("膨胀与腐蚀", grad_all); 

结果:
这里写图片描述

8.查找轮廓,绘制轮廓
        IntPtr mem_storage = CvInvoke.cvCreateMemStorage(0);
        MCvSeq first_contour = new MCvSeq();
        IntPtr Dyncontour = new IntPtr();//存放检测到的图像块的首地址
        CvInvoke.cvFindContours(grad_all, mem_storage, ref Dyncontour, 
            StructSize.MCvContour, 
            Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL, 
            Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, 
            new Point(0, 0));
        IntPtr temp = first_contour.ptr;
        Seq<Point> DyncontourTemp1 = new Seq<Point>(Dyncontour, null);//方便对IntPtr类型进行操作
        Seq<Point> DyncontourTemp = DyncontourTemp1;
        for (; DyncontourTemp1 != null && DyncontourTemp1.Ptr.ToInt32() != 0; DyncontourTemp1 = DyncontourTemp1.HNext)
        {
            Rectangle rect = CvInvoke.cvBoundingRect(DyncontourTemp1, true);
            if (rect.Width > 20 && rect.Height > 20)
            {
                rect.Width += 50;
                rect.Height += 50;
                Point p1 = new Point(rect.X, rect.Y);
                Point p2 = new Point(rect.X + rect.Width, rect.Y + rect.Height);
                CvInvoke.cvRectangle(img_src, p1, p2, new MCvScalar(0, 0, 255), 2, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0);
            }
        }

最后的结果:
这里写图片描述

9.最后

从上图可以看出找到了其中两个二维码,但是多了一个轮廓,不过定位二维码的主要功能就是用于识别,识别不出来的定位块自然也就没有用了。如果定位一维码(水平或垂直方向),即两个方向梯度相减,效果也不错。当然,这种定位方法会出现这样一些不必要的小框,是不是可以通过大小再过滤一次呢?

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值