参考:https://blog.csdn.net/qiao_lili/article/details/83176480
网上关于C#结合EmguCv开发答题卡识别的资料很少,因为有做答题卡识别方面的需求,个人也只熟悉C#语言,找了半天也只找到一些通过C++、Python或matlab结合OpenCV来实现识别的例子,只好对着别人的例子尝试着翻译成EmguCv,还算成功。自己又针对答题卡识别封装了几个函数,记录在这留给需要的人。(得吐槽下,EmguCv在错误管理上还欠缺很多,经常出现莫名其妙的错误)
1.设置两个图片显示容器
ib_original.SizeMode = PictureBoxSizeMode.Zoom;
ib_original.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
ib_result.SizeMode = PictureBoxSizeMode.Zoom;
ib_result.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
2.载入要处理的图片
OpenFileDialog op = new OpenFileDialog();
if (op.ShowDialog() == DialogResult.OK)
{
Mat src = new Mat(op.FileName, Emgu.CV.CvEnum.LoadImageType.AnyColor);
ib_original.Image = src;
}
实例图片
3.获取当前图像的最大矩形边界
//获取当前图像的最大矩形边界
VectorOfVectorOfPoint result_contour = GetBoundaryOfPic(src);
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.