识别准考证号

首先确定模板准考证号的有效区域,截取有效区域后,进行有效数量的识别。

附方法

/// <summary>
/// 获取区域图形
/// </summary>
/// <param name="mat"></param>
/// <param name="xMin"></param>
/// <param name="xMax"></param>
/// <param name="yMin"></param>
/// <param name="yMax"></param>
/// <returns></returns>
private Mat WarpPerspective(Mat mat,int xMin,int xMax,int yMin,int yMax)
{
Mat src = new Mat();
//计算图形大小
PointF[] pts_src = new PointF[] { new PointF(xMin, yMin), new PointF(xMax, yMin) ,
new PointF(xMax, yMax) ,new PointF(xMin, yMax)};
//计算透视变换矩阵
PointF[] pts_target = new PointF[] { new PointF(0, 0), new PointF(xMax-xMin, 0) ,
new PointF(xMax-xMin, yMax-yMin) ,new PointF(0, yMax-yMin)};

//计算透视矩阵
Mat data = CvInvoke.GetPerspectiveTransform(pts_src, pts_target);
CvInvoke.WarpPerspective(mat, src, data, new Size(xMax - xMin, yMax - yMin));
return src;
}

/// <summary>
/// 保存区域模板信息
/// </summary>
/// <param name="xMin">区域左位置</param>
/// <param name="yMin">区域上位置</param>
/// <param name="isHor">区域名称</param>
/// <param name="isHor">是否横向排</param>
/// <param name="isNumber">是否值是数字</param>
/// <param name="isSelectMore">是否支持多选</param>
/// <param name="blockCount">块模板数量</param>
/// <param name="elementCount">块内元素数量</param>
/// <returns></returns>
private bool SaveSection(int xMin,int yMin, string sectionName,bool isHor,bool isNumber,bool isSelectMore, int blockCount,int elementCount)
{
int sumElement = blockCount * elementCount;//匹配的元素总数量
VectorOfVectorOfPoint selected_contours = GetIamgeDiscern(matTem, new Size(60, 40));
#region 绘制矩形
List<PointInfoModel> pointInfos = new List<PointInfoModel>();
foreach (var item in selected_contours.ToArrayOfArray().ToList())
{
var itemList = item.ToList();
int XMin = itemList.Min(it => it.X);
int XMax = itemList.Max(it => it.X);
int YMin = itemList.Min(it => it.Y);
int YMax = itemList.Max(it => it.Y);
pointInfos.Add(new PointInfoModel(XMin, XMax, YMin, YMax));
}
if (pointInfos.Count > 0)
{
pointInfos = pointInfos.OrderBy(it => it.XMin).OrderBy(it => it.YMin).ToList();

}
tboxAreaNum.Text = pointInfos.Count.ToString();
//var temp = PointOperation(pointInfos);
foreach (var item in pointInfos)
{
CvInvoke.Line(matTem, new Point(item.XMin, item.YMin), new Point(item.XMax, item.YMin), new MCvScalar(0, 0, 255), 1);
CvInvoke.Line(matTem, new Point(item.XMin, item.YMin), new Point(item.XMin, item.YMax), new MCvScalar(0, 0, 255), 1);
CvInvoke.Line(matTem, new Point(item.XMin, item.YMax), new Point(item.XMax, item.YMax), new MCvScalar(0, 0, 255), 1);
CvInvoke.Line(matTem, new System.Drawing.Point(item.XMax, item.YMin), new Point(item.XMax, item.YMax), new MCvScalar(0, 0, 255), 1);
//CvInvoke.PutText(matTem, $"{pointInfos.IndexOf(item)}", new Point(item.XMin + 15, item.YMin + 15), FontFace.HersheyComplex, 0.8f, new MCvScalar(255, 0, 0));
}
image2.Source = GetSource(matTem.Bitmap);
#endregion
List<ElementModel> listElementModel = ConvertByPoint(selected_contours);
if(listElementModel.Count!=sumElement)
{
System.Windows.MessageBox.Show("区域无效——匹配数量不对,请重新选择!" + listElementModel.Count);
return false;
}
//验证元素大小是否差距不大
int minWidth = listElementModel.Min(it => it.Width);
int maxWidth= listElementModel.Max(it => it.Width);
int minHeight = listElementModel.Min(it => it.Height);
int maxHeight= listElementModel.Max(it => it.Height);
if(maxHeight>minHeight+10|| maxWidth> minWidth+10)
{
System.Windows.MessageBox.Show("区域无效——元素大小不一致,请重新选择!");
return false;
}

//完善模板
SectionModel sectionModel = new SectionModel();
sectionModel.SectionName = sectionName;
//验证有效点
VectorOfVectorOfPoint selected_contours1 = GetIamgeDiscernMatching(matTem, new Size(4, 4));
if (selected_contours1.ToArrayOfArray().ToList().Count > 0)
{
int pxNumCount = 0;
while (selected_contours1.ToArrayOfArray().ToList().Count > 0)
{
pxNumCount++;
selected_contours1 = GetIamgeDiscernMatching(matTem, new Size(4, 4), 200, 400 + 100 * pxNumCount);
}
sectionModel.PxNum = 400 + 100 * pxNumCount;
}
if (!isHor)
{
listElementModel = listElementModel.OrderBy(it => it.XMin).ToList();
for (int i = 0; i < blockCount; i++)
{
List<ElementModel> listItem = new List<ElementModel>();
for (int j = 0; j <elementCount; j++)
{
listItem.Add(listElementModel[i * elementCount + j]);
}
listItem= listItem.OrderBy(it => it.YMin).ToList();
BlockModel blockModel = new BlockModel();
blockModel.BlockName = string.Format("第{0}列", i + 1);
blockModel.IsSelectMore = isSelectMore;
for (int j = 0; j < listItem.Count; j++)
{
ElementModel elementModel = new ElementModel(listItem[j].XMin + xMin, listItem[j].XMax + xMin, listItem[j].YMin + yMin, listItem[j].YMax + yMin);
elementModel.GetValue(isNumber, j);
blockModel.ElementModels.Add(elementModel);
}
sectionModel.BlockModels.Add(blockModel);
}
}
else
{
listElementModel = listElementModel.OrderBy(it => it.YMin).ToList();
for (int i = 0; i < blockCount; i++)
{
List<ElementModel> listItem = new List<ElementModel>();
for (int j = 0; j < elementCount; j++)
{
listItem.Add(listElementModel[i * elementCount + j]);
}
listItem = listItem.OrderBy(it => it.XMin).ToList();
BlockModel blockModel = new BlockModel();
blockModel.BlockName = string.Format("第{0}行", i + 1);
blockModel.IsSelectMore = isSelectMore;
for (int j = 0; j < listItem.Count; j++)
{
ElementModel elementModel = new ElementModel(listItem[j].XMin + xMin, listItem[j].XMax + xMin, listItem[j].YMin + yMin, listItem[j].YMax + yMin);
elementModel.GetValue(isNumber, j);
blockModel.ElementModels.Add(elementModel);
}
sectionModel.BlockModels.Add(blockModel);
}
}
templateModel.SectionModels.Clear();
templateModel.SectionModels.Add(sectionModel);

return true ;
}
private List<ElementModel> ConvertByPoint(VectorOfVectorOfPoint selected_contours)
{
List<ElementModel> pointInfos = new List<ElementModel>();
foreach (var item in selected_contours.ToArrayOfArray().ToList())
{
var itemList = item.ToList();
int XMin = itemList.Min(it => it.X);
int XMax = itemList.Max(it => it.X);
int YMin = itemList.Min(it => it.Y);
int YMax = itemList.Max(it => it.Y);
pointInfos.Add(new ElementModel(XMin, XMax, YMin, YMax));
}
return pointInfos;
}

猜你喜欢

转载自www.cnblogs.com/xiaoq-blog/p/10893609.html