基于EmguCv圆形答题卡识别的优化

本文介绍了如何使用EmguCv优化答题卡的圆形识别,增强了通用性,不仅限于5*5答题卡,同时修复了常见问题,并提供了统一图片规格和轮廓间距计算的方法。
摘要由CSDN通过智能技术生成

主要对答题卡通用性方面进行了优化(可不限于5*5的答题卡,对图片规格进行统一,可自动计算轮廓间距),并对一些容易出现的bug进行了修复。还需要手动控制统一后的图片大小规格及测量需要检测到的轮廓大小范围。

1.主要代码

Mat src = new Image<Bgr, byte>(ib_original.Image.Bitmap).Mat;

                //1.获取当前图像的最大矩形边界
                VectorOfVectorOfPoint result_contour = commonUse.GetBoundaryOfPic(src);

                //2.对图像进行矫正
                Mat mat_Perspective = commonUse.MyWarpPerspective(src, result_contour);

                //规范图像大小
                CvInvoke.Resize(mat_Perspective, mat_Perspective, new Size(656, 818), 0, 0, Emgu.CV.CvEnum.Inter.Cubic);

                //3.二值化处理(大于阈值取0,小于阈值取255。其中白色为0,黑色为255)
                Mat mat_threshold = new Mat();
                CvInvoke.Threshold(mat_Perspective, mat_threshold, 160, 255, Emgu.CV.CvEnum.ThresholdType.BinaryInv);
                //ib_result.Image = mat_threshold;

                //4.获取符合标准的轮廓(外接矩形宽、高大于50,需手动调整)
                VectorOfVectorOfPoint selected_contours = commonUse.GetContoursAboveGivenSize(mat_threshold, 50, 100, 50, 100);

                //5.获取行、列个数信息
                Size sizeOfRowAndColumn = commonUse.GetCountOfRowAndColumn(selected_contours);
                int countOfRow = sizeOfRowAndColumn.Width;
                int countOfColumn = sizeOfRowAndColumn.Height;

                if (countOfRow == 0 || countOfColumn == 0)
                {
                    //没有符合要求的轮廓时,显示二值化后的图像
                    ib_result.Image = mat_threshold;
                    return;
                }
                else
                {
                    //6.对轮廓进行分类排序,并获取分类排序后的二维数组
                    VectorOfVectorOfPoint[,] classed_contours = commonUse.ClassedOfContours(selected_contours, countOfRow, countOfColumn);

                    //7.检测答题者的选项
                    int[,] result_count = commonUse.GetResultArray(mat_threshold, classed_contours, countOfRow, countOfColumn);

                    //8.标示出答题者的选项
                    Mat temp_mat = commonUse.DrawResultContours(mat_Perspective, classed_contours, result_count);

                    ib_result.Image = temp_mat;
                }

2.调用模块代码

using System;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using System.Drawing;

namespace 圆形答题卡识别
{
    class CommonUse
    {
        /// <summary>
        /// 获取给定图像的最大矩形边界
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public VectorOfVectorOfPoint GetBoundaryOfPic(Mat src)
        {
            Mat dst = new Mat();
            Mat src_gray = new Mat();
            CvInvoke.CvtColor(src, src_gray, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);

            //边缘检测
            CvInvoke.Canny(src_gray, dst, 120, 180);

            //寻找答题卡矩形边界(最大的矩形)
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();//创建VectorOfVectorOfPoint数据类型用于存储轮廓

            CvInvoke.FindContours(dst, contours, null, Emgu.CV.CvEnum.RetrType.External,
                Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);//提取轮廓

            VectorOfVectorOfPoint result_contour = new VectorOfVectorOfPoint();//用于存储筛选过后的轮廓

            int ksize = contours.Size; //获取连通区域个数
            if (ksize == 1)
            {
                result_contour = contours;
            }
            else
            {
                double maxLength = -1;//用于保存轮廓周长的最大值
                int index = -1;//轮廓周长的最大值的序号
                for (int i = 0; i < ksize; i++)
                {
                    VectorOfPoint contour = contours[i];//获取独立的连通轮廓
                    double length = CvInvoke.ArcLength(contour, true);//计算连通轮廓的周长

                    if (length > maxLength)
                    {
                        maxLength = length;
                        index = i;
                    }
                }
                result_contour.Push(contours[index]);//筛选后的连通轮廓
            }
            return result_contour;
        }

        /// <summary>
        /// 进行透视操作,获取矫正后图像
        /// </summary>
        /// <param name="src"></param>
        /// <param name="result_contour"></param>
        public Mat MyWarpPerspective
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值