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 img_src = new Image(barcodeBitmap );

2.转为灰度图

Image imput_gray = new Image(img_src.Size);
CvInvoke.cvCvtColor(img_src, imput_gray, COLOR_CONVERSION.BGR2GRAY);

3.计算x,y方向梯度,相加

        Image grad_x1 = new Image(img_src.Size); 
        Image grad_y1 = new Image(img_src.Size);
        Image grad_all = new Image(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);

梯度图:
c# EmguCv定位二维码_第1张图片

4.平均模糊

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

平均模糊结果:
c# EmguCv定位二维码_第2张图片

5.二值化

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

二值化图片:
c# EmguCv定位二维码_第3张图片

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);

图片结果:
c# EmguCv定位二维码_第4张图片

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); 

结果:
c# EmguCv定位二维码_第5张图片

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 DyncontourTemp1 = new Seq(Dyncontour, null);//方便对IntPtr类型进行操作
        Seq 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);
            }
        }

最后的结果:
c# EmguCv定位二维码_第6张图片

9.最后

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

你可能感兴趣的:(opencv)