原文:Emgu-WPF学习使用-识别二维码的位置

   参考链接:http://blog.csdn.net/gaobobo138968/article/details/47663607

   我完全参照该链接实现了二维码的位置锁定,向原作者致敬。

   由于我使用的为最新版本的Emgu,很多封装函数调用方法有所变化,新手接触Emgu,尝试做了调整,部分参数也做了微调!

   我使用的Emgu版本:emgucv-windesktop 3.2.0.2682

   最终我实现的效果图如下:

前台xaml: 

 <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Image x:Name="Img1" Grid.Column="0" />
        <Image x:Name="Img2" Grid.Column="1" />
        <Image x:Name="Img3" Grid.Column="2" />
        <Image x:Name="Img4" Grid.Column="3" />
        <Image x:Name="Img5" Grid.Column="0" Grid.Row="1"/>
        <Image x:Name="Img6" Grid.Column="1" Grid.Row="1"/>
        <Image x:Name="Img7" Grid.Column="2" Grid.Row="1"/>
        <Viewbox Stretch="Fill" Grid.Column="3" Grid.Row="1">
            <Grid Width="1134" Height="850" Background="Silver">
                <Image x:Name="Img8"/>
                <Canvas x:Name="CvMainZm"/>
            </Grid>
        </Viewbox>
       
    </Grid>

后台源码:

        private void ShowImage(System.Windows.Controls.Image oImage, UMat src)
        {
            this.Dispatcher.Invoke(() => {
                oImage.Source = BitmapSourceConvert.ToBitmapSource(src);
            });
        }

        private void ShowBgrImage(System.Windows.Controls.Image oImage, Image<Bgr, byte> src)
        {
            this.Dispatcher.Invoke(() => {
                oImage.Source = BitmapSourceConvert.ToBitmapSource(src);
            });
        }

        private void ShowGrayImage(System.Windows.Controls.Image oImage, Image<Gray, byte> src)
        {
            this.Dispatcher.Invoke(() => {
                oImage.Source = BitmapSourceConvert.ToBitmapSource(src);
            });
        }

        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += MainWindow_Loaded;
        }

        //参考链接 http://blog.csdn.net/gaobobo138968/article/details/47663607
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            string sFile = AppDomain.CurrentDomain.BaseDirectory + "Test.jpg";

            System.Drawing.Image img = System.Drawing.Image.FromFile(sFile);
            Bitmap barcodeBitmap = new Bitmap(img);
            Image<Bgr, byte> img_src = new Image<Bgr, byte>(barcodeBitmap);

            this.ShowBgrImage(this.Img1, img_src);

            //灰度化
            Image<Gray, byte> imput_gray = new Image<Gray, byte>(img_src.Size);
            CvInvoke.CvtColor(img_src, imput_gray, ColorConversion.Bgr2Gray);
            this.ShowGrayImage(this.Img2, imput_gray);

            //计算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.Sobel(imput_gray, grad_x1, DepthType.Default, 0, 1, 3);
            CvInvoke.Sobel(imput_gray, grad_y1, DepthType.Default, 1, 0, 3);
            CvInvoke.Add(grad_x1, grad_y1, grad_all, null);
            this.ShowGrayImage(this.Img3, grad_all);

            // 高斯模糊
            grad_all = grad_all.SmoothGaussian(9);
            this.ShowGrayImage(this.Img4, grad_all);

            // 二值化
            CvInvoke.Threshold(grad_all, grad_all, 100, 255, ThresholdType.Binary);
            this.ShowGrayImage(this.Img5, grad_all);

            //消除裂缝
            Mat oMat1 = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, 
                new System.Drawing.Size(15, 15), new System.Drawing.Point(0, 0));
            CvInvoke.MorphologyEx(grad_all, grad_all, Emgu.CV.CvEnum.MorphOp.Close, oMat1, 
                new System.Drawing.Point(0, 0), 1, BorderType.Default,
                new MCvScalar(255, 0, 0, 255));
            this.ShowGrayImage(this.Img6, grad_all);

            //膨胀与腐蚀(消除杂点)
            Mat oMat2 = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle,
               new System.Drawing.Size(5, 5), new System.Drawing.Point(0, 0));
            CvInvoke.Erode(grad_all, grad_all, oMat2, new System.Drawing.Point(0, 0), 4, 
                BorderType.Default, new MCvScalar(255, 0, 0, 255));
            CvInvoke.Dilate(grad_all, grad_all, oMat2, new System.Drawing.Point(0, 0), 4,
                BorderType.Default, new MCvScalar(255, 0, 0, 255));
            this.ShowGrayImage(this.Img7, grad_all);

            //查找轮廓,绘制轮廓
            #region Find triangles and rectangles
            List<Triangle2DF> triangleList = new List<Triangle2DF>();
            List<RotatedRect> boxList = new List<RotatedRect>(); //a box is a rotated rectangle

            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                CvInvoke.FindContours(grad_all, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                int count = contours.Size;
                for (int i = 0; i < count; i++)
                {
                    using (VectorOfPoint contour = contours[i])
                    using (VectorOfPoint approxContour = new VectorOfPoint())
                    {
                        CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);
                        if (CvInvoke.ContourArea(approxContour, false) > 500)
                        {
                            if (approxContour.Size == 3)
                            {
                                System.Drawing.Point[] pts = approxContour.ToArray();
                                triangleList.Add(new Triangle2DF(
                                   pts[0],
                                   pts[1],
                                   pts[2]
                                   ));
                            }
                            else if (approxContour.Size == 4)
                            {
                                #region determine if all the angles in the contour are within [80, 100] degree
                                bool isRectangle = true;
                                System.Drawing.Point[] pts = approxContour.ToArray();
                                LineSegment2D[] edges = Emgu.CV.PointCollection.PolyLine(pts, true);

                                for (int j = 0; j < edges.Length; j++)
                                {
                                    double angle = Math.Abs(
                                       edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                    if (angle < 80 || angle > 100)
                                    {
                                        isRectangle = false;
                                        break;
                                    }
                                }
                                #endregion
                                
                                if (isRectangle)
                                {
                                    boxList.Add(CvInvoke.MinAreaRect(approxContour));
                                }
                            }
                        }
                    }
                }

            }

            //this.Img8.Source = new BitmapImage(new Uri(sFile));
            this.ShowGrayImage(this.Img8, grad_all);
            foreach (RotatedRect box in boxList)
            {
                System.Drawing.Point[] pts = Array.ConvertAll(box.GetVertices(), System.Drawing.Point.Round);

                for (int i = 0; i < pts.Length; i++)
                {
                    System.Drawing.Point point = pts[i];
                    System.Drawing.Point point1 = new System.Drawing.Point();
                    if (i == pts.Length-1)
                        point1 = pts[0];
                    else
                        point1 = pts[i + 1];

                    Line oLine = new Line();
                    oLine.Stroke = new SolidColorBrush(Colors.Red);
                    oLine.StrokeThickness = 5;
                    oLine.X1 = point.X;
                    oLine.Y1 = point.Y;

                    oLine.X2 = point1.X;
                    oLine.Y2 = point1.Y;
                    this.CvMainZm.Children.Add(oLine);
                }
            }
            #endregion
        }

     BitmapSourceConvert 类直接使用的SDK中的示例。

Emgu-WPF学习使用-识别二维码的位置的更多相关文章

  1. 【咸鱼教程】Egret可长按识别二维码(精确位置和大小)

    教程目录一 实现原理二 实现过程三 Demo下载 本教程是在Egret中实现长按识别的二维码,并可以精确定位二维码的位置和大小,支持横屏和竖屏. 一 实现原理 微信中长按识别二维码,需要长按jpg或p ...

  2. Pyqt+QRcode 生成 识别 二维码

    1.生成二维码 python生成二维码是件很简单的事,使用第三方库Python QRCode就可生成二维码,我用Pyqt给QRcode打个壳 一.python-qrcode介绍 python-qrco ...

  3. python实现树莓派生成并识别二维码

    python实现树莓派生成并识别二维码 参考来源:http://blog.csdn.net/Burgess_Liu/article/details/40397803 设备及环境 树莓派2代 官方系统R ...

  4. HTML5实现扫描识别二维码/生成二维码

    扫描识别二维码 思路: 1. 操作摄像头,获取图片.HTML5 WEBRTC的navigator.getUserMedia方法去实时获取摄像头资源.  2. 利用canvas使用相关算法分析图片识别图 ...

  5. iOS--iOS7摄像头识别二维码功能

    iOS–iOS7摄像头识别二维码功能 属性介绍: AVFoundation 框架基于以下几个类实现图像捕捉 ,通过这些类可以访问来自相机设备的原始数据并控制它的组件. AVCaptureDevice ...

  6. C# ZXing.Net生成二维码、识别二维码、生成带Logo的二维码(二)

    1.使用ZXint.Net生成带logo的二维码 /// <summary> /// 生成带Logo的二维码 /// </summary> /// <param name ...

  7. spa(单页应用)中,使用history模式时,微信长按识别二维码在ios下失效的问题

    spa(单页应用,vue)中,使用history模式时,微信长按识别二维码在ios下失效的问题. 触发条件: spa单页应用: 路由模式 history 从其他页面跳转到带有微信二维码识别的页面(不是 ...

  8. python3 树莓派 + usb摄像头 做颜色识别 二维码识别

    今天又啥也没干 我完蛋了哦  就是没办法沉下心来,咋办....还是先来条NLP吧.. 七,凡事必有至少三个解决方法 对事情只有一个方法的人,必陷入困境,因为别无选择. 对事情有两个方法的人也陷入困境, ...

  9. php 识别二维码(转载)

    近段需要写一个通过PHP来识别二维码的功能,在网上查了很久才解决问题.以此来记录下来解决问题的方法. 最开始找的方法是一个叫 php-zbarcode 的扩展,自己照着网上的安装步骤安装了 Image ...

随机推荐

  1. [React] Create & Deploy a Universal React App using Zeit Next

    In this lesson, we'll use next to create a universal React application with no configuration. We'll ...

  2. [D3] Create Labels from Numeric Data with Quantize Scales in D3 v4

    Sometimes data needs to be converted from a continuous range, like test scores, to a discrete set of ...

  3. ios开发Base64编码以及加密相关学习

    一:.Base64补充 ```objc 1.Base64简单说明 描述:Base64可以成为密码学的基石,非常重要. 特点:可以将任意的二进制数据进行Base64编码 结果:所有的数据都能被编码为并只 ...

  4. .NET Framework基础知识(三)(转载)

    .正则表达式:用一串字符验证是否符合一种规范,这个规范就是正则表达式. .正则表达式中常用的元字符: . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字 \s 匹配空白符 \d 匹配数 ...

  5. GoJS超详细入门(插件使用无非:引包、初始化、配参数(json)、引数据(json)四步)

    GoJS超详细入门(插件使用无非:引包.初始化.配参数(json).引数据(json)四步) 一.总结 一句话总结:插件使用无非:引包.初始化.配参数(json).引数据(json)四步. 1.goj ...

  6. 网络拓扑图js插件——jTopo应用

    jTopo官网:http://www.jtopo.com/ 1.特点: 基于HTML5 Canvas,不依赖其他库 2.应用: 效果: 源码github地址 在HTML页面中引入jtopo.min.j ...

  7. ie7easyui的书写要规范

    在书写easyui对象的属性,有时候习惯在,属性的末尾再加一个“,”,这个在高版本浏览器是没事的,但是在ie7及以下,会有报错

  8. <a href='javacript:' title='{$str}'>是什么意思(多看学习视频)

    <a href='javacript:' title='{$str}'>是什么意思(多看学习视频) 一.总结 一句话总结: 1.javascript:是什么? 伪协议,后面接javascr ...

  9. 使用apidoc 生成Restful web Api文档

    在项目开发过程中,总会牵扯到接口文档的设计与编写,之前使用的都是office工具,写一个文档,总也是不够漂亮和直观.好在git上的开源大神提供了生成文档的工具,so来介绍一下! 该工具是Nodejs的 ...

  10. [Flow] Declare types for application

    In Flow, you can make global declarion about types. Run: flow init It will generate .flowconfig file ...