1577 lines
56 KiB
C#
1577 lines
56 KiB
C#
using Emgu.CV;
|
||
using Emgu.CV.CvEnum;
|
||
using Emgu.CV.Structure;
|
||
using Emgu.CV.UI;
|
||
using Emgu.CV.Util;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Web;
|
||
|
||
|
||
public 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, 20, 255, 3, true);
|
||
|
||
//寻找答题卡矩形边界(最大的矩形)
|
||
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();//创建VectorOfVectorOfPoint数据类型用于存储轮廓
|
||
|
||
CvInvoke.FindContours(dst, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);//提取轮廓
|
||
|
||
VectorOfVectorOfPoint max_contour = new VectorOfVectorOfPoint();//用于存储筛选过后的轮廓
|
||
|
||
int ksize = contours.Size; //获取连通区域个数
|
||
if (ksize == 1)
|
||
{
|
||
max_contour = contours;
|
||
}
|
||
else
|
||
{
|
||
//double maxLength = -1;//用于保存轮廓周长的最大值
|
||
double maxArea = -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;
|
||
//}
|
||
|
||
double area = CvInvoke.ContourArea(contour, false);
|
||
if (area > maxArea)
|
||
{
|
||
maxArea = area;
|
||
index = i;
|
||
}
|
||
}
|
||
max_contour.Push(contours[index]);//筛选后的连通轮廓
|
||
}
|
||
return max_contour;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 进行透视操作,获取矫正后图像
|
||
/// </summary>
|
||
/// <param name="src"></param>
|
||
/// <param name="result_contour"></param>
|
||
public Mat MyWarpPerspective(Mat src, VectorOfVectorOfPoint max_contour)
|
||
{
|
||
//拟合答题卡的几何轮廓,保存点集pts并顺时针排序
|
||
VectorOfPoint pts = new VectorOfPoint();//用于存放逼近的结果
|
||
VectorOfPoint tempContour = max_contour[0];//临时用
|
||
double result_length = CvInvoke.ArcLength(tempContour, true);
|
||
CvInvoke.ApproxPolyDP(tempContour, pts, result_length * 0.02, true); //几何逼近,获取矩形4个顶点坐标
|
||
|
||
if (pts.Size != 4)
|
||
{
|
||
//最大轮廓不是矩形时,将原图转灰度图后返回
|
||
Mat src_gray = new Mat();
|
||
CvInvoke.CvtColor(src, src_gray, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);//转灰度图
|
||
return src_gray;
|
||
}
|
||
else
|
||
{
|
||
//Point[]转换为PointF[]类型
|
||
PointF[] pts_src = Array.ConvertAll(pts.ToArray(), new Converter<Point, PointF>(PointToPointF));
|
||
|
||
//点集顺时针排序
|
||
pts_src = SortPointsByClockwise(pts_src);
|
||
|
||
//确定透视变换的宽度、高度
|
||
Size sizeOfRect = CalSizeOfRect(pts_src);
|
||
int width = src.Bitmap.Width;
|
||
int height = src.Bitmap.Height;
|
||
|
||
//计算透视变换矩阵
|
||
PointF[] pts_target = new PointF[] { new PointF(0, 0), new PointF(width - 1, 0) ,
|
||
new PointF(width - 1, height - 1) ,new PointF(0, height - 1)};
|
||
|
||
//计算透视矩阵
|
||
Mat data = CvInvoke.GetPerspectiveTransform(pts_src, pts_target);
|
||
//进行透视操作
|
||
Mat src_gray = new Mat();
|
||
Mat mat_Perspective = new Mat();
|
||
CvInvoke.CvtColor(src, src_gray, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);
|
||
CvInvoke.WarpPerspective(src_gray, mat_Perspective, data, new Size(width, height));
|
||
|
||
return mat_Perspective;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据给定XY初始坐标、间距、数量画网格
|
||
/// </summary>
|
||
/// <param name="mat"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="x_interval"></param>
|
||
/// <param name="x_num"></param>
|
||
/// <param name="y"></param>
|
||
/// <param name="y_interval"></param>
|
||
/// <param name="y_num"></param>
|
||
/// <returns></returns>
|
||
public Bitmap DrawGridByXYDraw(Bitmap bmp, int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num)
|
||
{
|
||
|
||
|
||
Mat src = new Image<Bgr, byte>(bmp).Mat;
|
||
//转换颜色空间
|
||
Mat mat_color = new Mat();
|
||
if (src.NumberOfChannels == 1)
|
||
CvInvoke.CvtColor(src, mat_color, Emgu.CV.CvEnum.ColorConversion.Gray2Bgr);
|
||
else
|
||
mat_color = src;
|
||
|
||
for (int i = 0; i <= x_num; i++)
|
||
{
|
||
//先画竖线
|
||
Point p1 = new Point(x_begin + x_interval * i, y_begin);
|
||
Point p2 = new Point(x_begin + x_interval * i, y_begin + y_interval * y_num);
|
||
CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 2);
|
||
}
|
||
for (int i = 0; i <= y_num; i++)
|
||
{
|
||
//再画横线
|
||
Point p1 = new Point(x_begin, y_begin + y_interval * i);
|
||
Point p2 = new Point(x_begin + x_interval * x_num, y_begin + y_interval * i);
|
||
CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 2);
|
||
}
|
||
return mat_color.Bitmap;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取偏移量 通过矩形查找
|
||
/// </summary>
|
||
/// <param name="bmp"></param>
|
||
/// <param name="PointPath"></param>
|
||
/// <param name="PostionXY"></param>
|
||
/// <param name="width"></param>
|
||
/// <param name="height"></param>
|
||
/// <returns></returns>
|
||
public Mat GetPostionXYByFindPostionAndXieLv(Mat color_mat, VectorOfVectorOfPoint selected_contours, string postionCut, out string PYPostion, Image<Gray, byte> currentFrame, out double xielv)
|
||
{
|
||
|
||
|
||
CommonUse commonUse = new CommonUse();
|
||
string[] postionc = postionCut.Split(new string[] { "^" }, StringSplitOptions.RemoveEmptyEntries);
|
||
PYPostion = "";
|
||
Point GrXY;
|
||
int PostionWW = 0;
|
||
int PostionHH = 0;
|
||
|
||
int Y2 = 0, Y1 = 0, X2 = 0, X1 = 0;
|
||
|
||
for (int i = 0; i < postionc.Length; i++)
|
||
{
|
||
string[] postCutList = postionc[i].Split(',');
|
||
int X = Convert.ToInt32(Convert.ToDouble(postCutList[0]));
|
||
int Y = Convert.ToInt32(Convert.ToDouble(postCutList[1]));
|
||
int W = Convert.ToInt32(Convert.ToDouble(postCutList[2]));
|
||
int H = Convert.ToInt32(Convert.ToDouble(postCutList[3]));
|
||
|
||
//var aaa=commonUse.DrawGridByXY(color_mat, X, W, 1, Y, H, 1);
|
||
//ShowMatWaitKey("123", aaa, 0.8);
|
||
|
||
string mx = "";
|
||
try
|
||
{
|
||
mx = commonUse.GetValueAndDrawGrid_Find(color_mat.Bitmap, selected_contours, X, W, 1, Y, H, 1, "", out GrXY);
|
||
}
|
||
catch
|
||
{
|
||
xielv = -100;
|
||
return null;
|
||
mx = "null";
|
||
GrXY = new Point(0, 0);
|
||
}
|
||
|
||
if (mx.Trim() != "A")
|
||
{
|
||
xielv = -100;
|
||
return null;
|
||
break;
|
||
}
|
||
Point Mx = GrXY;
|
||
if (i == 0)//左上角
|
||
{
|
||
PYPostion = GrXY.X + "," + GrXY.Y;
|
||
Y1 = GrXY.Y;
|
||
X1 = GrXY.X;
|
||
}
|
||
if (i == 1)//右上角
|
||
{
|
||
PostionWW = GrXY.X;
|
||
}
|
||
if (i == 2)//左下角
|
||
{
|
||
PostionHH = GrXY.Y;
|
||
X2 = GrXY.X;
|
||
Y2 = GrXY.Y;
|
||
}
|
||
}
|
||
string[] posList = PYPostion.Split(',');
|
||
xielv = Math.Atan2((Y2 - Y1), (X2 - X1)) * 180 / Math.PI;
|
||
int PostionX = Convert.ToInt32(posList[0]);
|
||
int PostionY = Convert.ToInt32(posList[1]);
|
||
int PostionW = PostionWW - PostionX;
|
||
int PostionH = PostionHH - PostionY;
|
||
//裁剪
|
||
Rectangle rectangle = new Rectangle(PostionX, PostionY, PostionW, PostionH);
|
||
Image<Gray, byte> Sub = new Image<Gray, byte>(currentFrame.Bitmap).GetSubRect(rectangle);
|
||
Image<Gray, byte> CropImage = new Image<Gray, byte>(Sub.Size);
|
||
CvInvoke.cvCopy(Sub, CropImage, IntPtr.Zero);
|
||
//获取偏移量
|
||
return CropImage.Mat;
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将给定点集顺时针排序
|
||
/// </summary>
|
||
/// <param name="pts_src">四边形四个顶点组成的点集</param>
|
||
/// <returns></returns>
|
||
public PointF[] SortPointsByClockwise(PointF[] pts_src)
|
||
{
|
||
if (pts_src.Length != 4) return null;//确保为四边形
|
||
|
||
//求四边形中心点?坐标
|
||
float x_average = 0;
|
||
float y_average = 0;
|
||
float x_sum = 0;
|
||
float y_sum = 0;
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
x_sum += pts_src[i].X;
|
||
y_sum += pts_src[i].Y;
|
||
}
|
||
x_average = x_sum / 4;
|
||
y_average = y_sum / 4;
|
||
PointF center = new PointF(x_average, y_average);
|
||
|
||
PointF[] result = new PointF[4];
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
if (pts_src[i].X < center.X && pts_src[i].Y < center.Y)
|
||
{
|
||
result[0] = pts_src[i];//左上角点
|
||
continue;
|
||
}
|
||
if (pts_src[i].X > center.X && pts_src[i].Y < center.Y)
|
||
{
|
||
result[1] = pts_src[i];//右上角点
|
||
continue;
|
||
}
|
||
if (pts_src[i].X > center.X && pts_src[i].Y > center.Y)
|
||
{
|
||
result[2] = pts_src[i];//右下角点
|
||
continue;
|
||
}
|
||
if (pts_src[i].X < center.X && pts_src[i].Y > center.Y)
|
||
{
|
||
result[3] = pts_src[i];//左下角点
|
||
continue;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算给定四个坐标点四边形的宽、高
|
||
/// </summary>
|
||
/// <param name="pts_src"></param>
|
||
/// <returns></returns>
|
||
public Size CalSizeOfRect(PointF[] pts_src)
|
||
{
|
||
if (pts_src.Length != 4) return new Size(0, 0);//确保为四边形
|
||
|
||
//点集顺时针排序
|
||
pts_src = SortPointsByClockwise(pts_src);
|
||
|
||
//确定透视变换的宽度、高度
|
||
int width;
|
||
int height;
|
||
|
||
double width1 = Math.Pow(pts_src[0].X - pts_src[1].X, 2) + Math.Pow(pts_src[0].Y - pts_src[1].Y, 2);
|
||
double width2 = Math.Pow(pts_src[2].X - pts_src[3].X, 2) + Math.Pow(pts_src[2].Y - pts_src[3].Y, 2);
|
||
|
||
width = width1 > width2 ? (int)Math.Sqrt(width1) : (int)Math.Sqrt(width2);//根号下a方+b方,且取宽度最大的
|
||
|
||
double height1 = Math.Pow(pts_src[0].X - pts_src[3].X, 2) + Math.Pow(pts_src[0].Y - pts_src[3].Y, 2);
|
||
double height2 = Math.Pow(pts_src[1].X - pts_src[2].X, 2) + Math.Pow(pts_src[1].Y - pts_src[2].Y, 2);
|
||
|
||
height = height1 > height2 ? (int)Math.Sqrt(height1) : (int)Math.Sqrt(height2);
|
||
|
||
return new Size(width, height);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Point转换为PointF类型
|
||
/// </summary>
|
||
/// <param name="p"></param>
|
||
/// <returns></returns>
|
||
public static PointF PointToPointF(Point p)
|
||
{
|
||
return new PointF(p.X, p.Y);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 形态学膨胀
|
||
/// </summary>
|
||
/// <param name="mat"></param>
|
||
/// <returns></returns>
|
||
public Mat MyDilate(Mat mat)
|
||
{
|
||
//1.膨胀,改善轮廓
|
||
Mat struct_element = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Cross,
|
||
new Size(3, 3), new Point(-1, -1));//结构元素
|
||
Mat mat_dilate = new Mat();
|
||
CvInvoke.MorphologyEx(mat, mat_dilate, Emgu.CV.CvEnum.MorphOp.Dilate, struct_element, new Point(-1, -1), 1,
|
||
Emgu.CV.CvEnum.BorderType.Default, new MCvScalar(0, 0, 0));//形态学膨胀
|
||
|
||
return mat_dilate;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 筛选图中符合给定条件的轮廓
|
||
/// </summary>
|
||
/// <param name="mat_threshold">要提取轮廓的图片</param>
|
||
/// <param name="width1">轮廓外接矩形大于该宽度值</param>
|
||
/// <param name="width2">轮廓外接矩形小于该宽度值</param>
|
||
/// <param name="height1">轮廓外接矩形大于该高度值</param>
|
||
/// <param name="height2">轮廓外接矩形小于该高度值</param>
|
||
public VectorOfVectorOfPoint GetUsefulContours(Mat mat, double ratio)
|
||
{
|
||
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();//所有的轮廓
|
||
VectorOfVectorOfPoint selected_contours = new VectorOfVectorOfPoint();//用于存储筛选过后的轮廓
|
||
CvInvoke.FindContours(mat, contours, null, Emgu.CV.CvEnum.RetrType.List,
|
||
Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);//提取所有轮廓,操作过程中会对输入图像进行修改
|
||
|
||
//筛选轮廓。筛选条件:长宽比大于给定值
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);//外接矩形
|
||
Mat temp = new Mat(mat, rect);//提取ROI矩形区域
|
||
int pxNums = CvInvoke.CountNonZero(temp);//计算图像内非零像素个数
|
||
|
||
double area = CvInvoke.ContourArea(contours[i]);//计算连通轮廓的面积
|
||
double length = CvInvoke.ArcLength(contours[i], false); //计算连通轮廓的周长
|
||
|
||
VectorOfPoint approx_curve = new VectorOfPoint();//用于存放逼近的结果
|
||
CvInvoke.ApproxPolyDP(contours[i], approx_curve, length * 0.05, true);
|
||
bool bo = ((rect.Width > 8 && rect.Height > 3) && (area > 200 && area < 8000) && (rect.Width < 50 && rect.Height < 50) && pxNums > 100);
|
||
if (bo)
|
||
{
|
||
selected_contours.Push(contours[i]);
|
||
}
|
||
}
|
||
|
||
return selected_contours;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 筛选图中符合给定条件的轮廓
|
||
/// </summary>
|
||
/// <param name="mat_threshold">要提取轮廓的图片</param>
|
||
/// <param name="width1">轮廓外接矩形大于该宽度值</param>
|
||
/// <param name="width2">轮廓外接矩形小于该宽度值</param>
|
||
/// <param name="height1">轮廓外接矩形大于该高度值</param>
|
||
/// <param name="height2">轮廓外接矩形小于该高度值</param>
|
||
public VectorOfVectorOfPoint GetUsefulContoursDingWei(Mat mat, double ratio)
|
||
{
|
||
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();//所有的轮廓
|
||
VectorOfVectorOfPoint selected_contours = new VectorOfVectorOfPoint();//用于存储筛选过后的轮廓
|
||
CvInvoke.FindContours(mat, contours, null, Emgu.CV.CvEnum.RetrType.External,
|
||
Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);//提取所有轮廓,操作过程中会对输入图像进行修改
|
||
|
||
//筛选轮廓。筛选条件:长宽比大于给定值
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
// 像素点数筛选
|
||
//if (contours[i].Size <= 8 )
|
||
//{
|
||
// continue;
|
||
//}
|
||
|
||
Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);//外接矩形
|
||
Mat temp = new Mat(mat, rect);//提取ROI矩形区域
|
||
int pxNums = CvInvoke.CountNonZero(temp);//计算图像内非零像素个数
|
||
|
||
double area = CvInvoke.ContourArea(contours[i]);//计算连通轮廓的面积
|
||
double length = CvInvoke.ArcLength(contours[i], false); //计算连通轮廓的周长
|
||
|
||
VectorOfPoint approx_curve = new VectorOfPoint();//用于存放逼近的结果
|
||
CvInvoke.ApproxPolyDP(contours[i], approx_curve, length * 0.05, true);
|
||
|
||
//外接矩形宽、高需在给定范围内
|
||
// bool bo = (rect.Width / rect.Height >= ratio && (rect.Width > 3 && rect.Height > 2) && (area > 200 && area <= 4500));
|
||
//bool bo = ((rect.Width > 3 && rect.Height > 2) && (area > 80 && area <= 15000));
|
||
//bool bo = pxNums > 130 && pxNums < 300;
|
||
bool bo = (approx_curve.Size == 4 && CvInvoke.IsContourConvex(approx_curve) && (rect.Width > 15 && rect.Height > 15) && (area > 550 && area < 2000) && (rect.Width < 50 && rect.Height < 50) && pxNums > 550);
|
||
if (bo)
|
||
{
|
||
selected_contours.Push(contours[i]);
|
||
}
|
||
}
|
||
return selected_contours;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 筛选图中符合给定条件的轮廓
|
||
/// </summary>
|
||
/// <param name="mat_threshold">要提取轮廓的图片</param>
|
||
/// <param name="width1">轮廓外接矩形大于该宽度值</param>
|
||
/// <param name="width2">轮廓外接矩形小于该宽度值</param>
|
||
/// <param name="height1">轮廓外接矩形大于该高度值</param>
|
||
/// <param name="height2">轮廓外接矩形小于该高度值</param>
|
||
public VectorOfVectorOfPoint GetUsefulContoursDingWeiSanJiao(Mat mat, double ratio)
|
||
{
|
||
|
||
VectorOfVectorOfPoint selected_contours = new VectorOfVectorOfPoint();
|
||
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
|
||
{
|
||
// 参数:输入图像,点向量,,检索类型,方法
|
||
CvInvoke.FindContours(mat, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
using (VectorOfPoint contour = contours[i]) //点的标准矢量
|
||
using (VectorOfPoint approxContour = new VectorOfPoint())
|
||
{
|
||
// CvInvoke.ApproxPolyDP:指定精度的多边形曲线 参数:输入向量(轮廓),近似轮廓,近似精度,true:则闭合形状
|
||
// CvInvoke.ArcLength:计算轮廓长度 参数:轮廓,曲线是否闭合
|
||
CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.08, true); //0.08的相似度
|
||
//CvInvoke.ContourArea:计算轮廓面积 参数:轮廓,返回值是否为绝对值
|
||
//仅考虑面积大于50的轮廓
|
||
if (CvInvoke.ContourArea(approxContour, false) > 500)
|
||
{
|
||
if (approxContour.Size == 3)//轮廓有3个顶点:三角形
|
||
{
|
||
Point[] points = approxContour.ToArray(); //转化为数组
|
||
selected_contours.Push(contours[i]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return selected_contours;
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 筛选图中符合给定条件的轮廓
|
||
/// </summary>
|
||
/// <param name="mat_threshold">要提取轮廓的图片</param>
|
||
/// <param name="width1">轮廓外接矩形大于该宽度值</param>
|
||
/// <param name="width2">轮廓外接矩形小于该宽度值</param>
|
||
/// <param name="height1">轮廓外接矩形大于该高度值</param>
|
||
/// <param name="height2">轮廓外接矩形小于该高度值</param>
|
||
public VectorOfVectorOfPoint GetUsefulContoursYueJuan(Mat mat, double ratio)
|
||
{
|
||
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();//所有的轮廓
|
||
VectorOfVectorOfPoint selected_contours = new VectorOfVectorOfPoint();//用于存储筛选过后的轮廓
|
||
CvInvoke.FindContours(mat, contours, null, Emgu.CV.CvEnum.RetrType.List,
|
||
Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);//提取所有轮廓,操作过程中会对输入图像进行修改
|
||
|
||
//筛选轮廓。筛选条件:长宽比大于给定值
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);//外接矩形
|
||
Mat temp = new Mat(mat, rect);//提取ROI矩形区域
|
||
int pxNums = CvInvoke.CountNonZero(temp);//计算图像内非零像素个数
|
||
|
||
double area = CvInvoke.ContourArea(contours[i]);//计算连通轮廓的面积
|
||
double length = CvInvoke.ArcLength(contours[i], false); //计算连通轮廓的周长
|
||
|
||
VectorOfPoint approx_curve = new VectorOfPoint();//用于存放逼近的结果
|
||
CvInvoke.ApproxPolyDP(contours[i], approx_curve, length * 0.02, true);
|
||
|
||
//外接矩形宽、高需在给定范围内
|
||
bool bo = (rect.Width / rect.Height >= ratio && (rect.Width > 3 && rect.Height > 2) && (area > 200 && area <= 4500));
|
||
// bool bo = ((rect.Width > 3 && rect.Height > 2) && (area > 200 && area <= 4500));
|
||
//bool bo = ((rect.Width > 3 && rect.Height > 2) && (area > 200 && area <= 4500));
|
||
//bool bo = pxNums > 130 && pxNums < 300;
|
||
if (bo)
|
||
{
|
||
selected_contours.Push(contours[i]);
|
||
}
|
||
}
|
||
|
||
return selected_contours;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 根据给定的轮廓及范围信息计算涂卡的结果,返回int数组
|
||
/// </summary>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="x_interval"></param>
|
||
/// <param name="x_num"></param>
|
||
/// <param name="y"></param>
|
||
/// <param name="y_interval"></param>
|
||
/// <param name="y_num"></param>
|
||
/// <returns></returns>
|
||
public int[] GetTargetGravityFind(VectorOfVectorOfPoint contours, int x_begin, int x_interval, int x_num,
|
||
int y_begin, int y_interval, int y_num, out Point gravityXY)
|
||
{
|
||
int[] result = new int[x_num];//结果数组
|
||
//数组初值默认为-1
|
||
for (int i = 0; i < x_num; i++)
|
||
{
|
||
result[i] = -1;
|
||
}
|
||
int x_max = x_begin + x_interval * x_num;
|
||
int y_max = y_begin + y_interval * y_num;
|
||
VectorOfVectorOfPoint targetContours = new VectorOfVectorOfPoint();
|
||
Point[] gravity = GetGravityOfContours(contours);//轮廓中心点坐标
|
||
|
||
gravityXY = new Point(0, 0);
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
VectorOfPoint contour = contours[i];
|
||
if (gravity[i].X < x_begin || gravity[i].X > x_max || gravity[i].Y < y_begin || gravity[i].Y > y_max)
|
||
{
|
||
continue;//判断中心点是否超出范围
|
||
}
|
||
int x_id = (int)Math.Floor((double)(gravity[i].X - x_begin) / x_interval);//向下取整
|
||
int value = (int)Math.Floor((double)(gravity[i].Y - y_begin) / y_interval);
|
||
|
||
if (result[x_id] != -1)
|
||
{
|
||
string str = string.Format("第{0}列存在多个答案!请擦拭干净后再扫描", x_id);
|
||
result[x_id] = Convert.ToInt32(result[x_id].ToString() + value.ToString());
|
||
gravityXY = gravity[i];
|
||
|
||
}
|
||
else
|
||
{
|
||
Rectangle rect = CvInvoke.BoundingRectangle(contour);
|
||
//这里有修改
|
||
result[x_id] = value;
|
||
gravityXY = gravity[i];
|
||
gravityXY.X = rect.X;
|
||
gravityXY.Y = rect.Y;
|
||
break;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 根据给定的轮廓及范围信息计算涂卡的结果,返回int数组
|
||
/// </summary>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="x_interval"></param>
|
||
/// <param name="x_num"></param>
|
||
/// <param name="y"></param>
|
||
/// <param name="y_interval"></param>
|
||
/// <param name="y_num"></param>
|
||
/// <returns></returns>
|
||
public int[] GetTargetValues(VectorOfVectorOfPoint contours, int x_begin, int x_interval, int x_num,
|
||
int y_begin, int y_interval, int y_num)
|
||
{
|
||
int[] result = new int[x_num];//结果数组
|
||
//数组初值默认为-1
|
||
for (int i = 0; i < x_num; i++)
|
||
{
|
||
result[i] = -1;
|
||
}
|
||
int x_max = x_begin + x_interval * x_num;
|
||
int y_max = y_begin + y_interval * y_num;
|
||
VectorOfVectorOfPoint targetContours = new VectorOfVectorOfPoint();
|
||
Point[] gravity = GetGravityOfContours(contours);//轮廓中心点坐标
|
||
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
VectorOfPoint contour = contours[i];
|
||
if (gravity[i].X < x_begin || gravity[i].X > x_max || gravity[i].Y < y_begin || gravity[i].Y > y_max)
|
||
{
|
||
continue;//判断中心点是否超出范围
|
||
}
|
||
int x_id = (int)Math.Floor((double)(gravity[i].X - x_begin) / x_interval);//向下取整
|
||
int value = (int)Math.Floor((double)(gravity[i].Y - y_begin) / y_interval);
|
||
|
||
if (result[x_id] != -1)
|
||
{
|
||
string str = string.Format("第{0}列存在多个答案!请擦拭干净后再扫描", x_id);
|
||
//MessageBox.Show(x_id.ToString());
|
||
result[x_id] = Convert.ToInt32(result[x_id].ToString() + value.ToString());
|
||
//result[x_id] = -1;
|
||
}
|
||
else
|
||
{
|
||
result[x_id] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据给定的轮廓及范围信息计算涂卡的结果,返回int数组
|
||
/// </summary>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="x_interval"></param>
|
||
/// <param name="x_num"></param>
|
||
/// <param name="y"></param>
|
||
/// <param name="y_interval"></param>
|
||
/// <param name="y_num"></param>
|
||
/// <returns></returns>
|
||
public int[] GetTargetValuesOnlyOne(VectorOfVectorOfPoint contours, int x_begin, int x_interval, int x_num,
|
||
int y_begin, int y_interval, int y_num)
|
||
{
|
||
int[] result = new int[x_num];//结果数组
|
||
//数组初值默认为-1
|
||
for (int i = 0; i < x_num; i++)
|
||
{
|
||
result[i] = -1;
|
||
}
|
||
int x_max = x_begin + x_interval * x_num;
|
||
int y_max = y_begin + y_interval * y_num;
|
||
VectorOfVectorOfPoint targetContours = new VectorOfVectorOfPoint();
|
||
Point[] gravity = GetGravityOfContours(contours);//轮廓中心点坐标
|
||
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
VectorOfPoint contour = contours[i];
|
||
if (gravity[i].X < x_begin || gravity[i].X > x_max || gravity[i].Y < y_begin || gravity[i].Y > y_max)
|
||
{
|
||
continue;//判断中心点是否超出范围
|
||
}
|
||
int x_id = (int)Math.Floor((double)(gravity[i].X - x_begin) / x_interval);//向下取整
|
||
int value = (int)Math.Floor((double)(gravity[i].Y - y_begin) / y_interval);
|
||
|
||
if (result[x_id] != -1)
|
||
{
|
||
//string str = string.Format("第{0}列存在多个答案!请擦拭干净后再扫描", x_id);
|
||
//MessageBox.Show(x_id.ToString());
|
||
//result[x_id] = Convert.ToInt32(result[x_id].ToString() + value.ToString());
|
||
//result[x_id] = -1;
|
||
}
|
||
else
|
||
{
|
||
result[x_id] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
// <summary>
|
||
/// 根据给定的轮廓及范围信息计算涂卡的结果,返回int数组
|
||
/// </summary>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="x_interval"></param>
|
||
/// <param name="x_num"></param>
|
||
/// <param name="y"></param>
|
||
/// <param name="y_interval"></param>
|
||
/// <param name="y_num"></param>
|
||
/// <returns></returns>
|
||
public int[] GetTargetValues_L(VectorOfVectorOfPoint contours, int x_begin, int x_interval, int x_num,
|
||
int y_begin, int y_interval, int y_num)
|
||
{
|
||
int[] result = new int[y_num];//结果数组
|
||
//数组初值默认为-1
|
||
for (int i = 0; i < y_num; i++)
|
||
{
|
||
result[i] = -1;
|
||
}
|
||
int x_max = x_begin + x_interval * x_num;
|
||
int y_max = y_begin + y_interval * y_num;
|
||
|
||
|
||
VectorOfVectorOfPoint targetContours = new VectorOfVectorOfPoint();
|
||
Point[] gravity = GetGravityOfContours(contours);//轮廓中心点坐标
|
||
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
VectorOfPoint contour = contours[i];
|
||
|
||
if (gravity[i].X < x_begin || gravity[i].X > x_max || gravity[i].Y < y_begin || gravity[i].Y > y_max)
|
||
{
|
||
continue;//判断中心点是否超出范围
|
||
}
|
||
|
||
int x_id = (int)Math.Floor((double)(gravity[i].Y - y_begin) / y_interval);//向右取整数
|
||
int value = (int)Math.Floor((double)(gravity[i].X - x_begin) / x_interval);
|
||
|
||
if (result[x_id] != -1)
|
||
{
|
||
string str = string.Format("第{0}列存在多个答案!请擦拭干净后再扫描", x_id);
|
||
result[x_id] = Convert.ToInt32(result[x_id].ToString() + value.ToString());
|
||
|
||
}
|
||
else
|
||
{
|
||
result[x_id] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
// <summary>
|
||
/// 根据给定的轮廓及范围信息计算涂卡的结果,返回int数组
|
||
/// </summary>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="x_interval"></param>
|
||
/// <param name="x_num"></param>
|
||
/// <param name="y"></param>
|
||
/// <param name="y_interval"></param>
|
||
/// <param name="y_num"></param>
|
||
/// <returns></returns>
|
||
public int[] GetTargetValues_L_only(VectorOfVectorOfPoint contours, int x_begin, int x_interval, int x_num,
|
||
int y_begin, int y_interval, int y_num)
|
||
{
|
||
int[] result = new int[y_num];//结果数组
|
||
//数组初值默认为-1
|
||
for (int i = 0; i < y_num; i++)
|
||
{
|
||
result[i] = -1;
|
||
}
|
||
int x_max = x_begin + x_interval * x_num;
|
||
int y_max = y_begin + y_interval * y_num;
|
||
|
||
|
||
VectorOfVectorOfPoint targetContours = new VectorOfVectorOfPoint();
|
||
Point[] gravity = GetGravityOfContours(contours);//轮廓中心点坐标
|
||
|
||
for (int i = 0; i < contours.Size; i++)
|
||
{
|
||
VectorOfPoint contour = contours[i];
|
||
|
||
if (gravity[i].X < x_begin || gravity[i].X > x_max || gravity[i].Y < y_begin || gravity[i].Y > y_max)
|
||
{
|
||
continue;//判断中心点是否超出范围
|
||
}
|
||
|
||
int x_id = (int)Math.Floor((double)(gravity[i].Y - y_begin) / y_interval);//向右取整数
|
||
int value = (int)Math.Floor((double)(gravity[i].X - x_begin) / x_interval);
|
||
|
||
if (result[x_id] != -1)
|
||
{
|
||
//string str = string.Format("第{0}列存在多个答案!请擦拭干净后再扫描", x_id);
|
||
//result[x_id] = Convert.ToInt32(result[x_id].ToString() + value.ToString());
|
||
|
||
}
|
||
else
|
||
{
|
||
result[x_id] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
//public string GetValueAndDrawGridZhunKao(ImageBox img, VectorOfVectorOfPoint contours,
|
||
// int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
//{
|
||
// //画网格
|
||
// //Mat src = new Image<Bgr, byte>(img.Image.Bitmap).Mat;
|
||
// //Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
|
||
// int[] intArray = GetTargetValues(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
// int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
|
||
// string str = "";
|
||
// //str += Environment.NewLine;//回车
|
||
// str += strText;
|
||
|
||
// str += GetStringOfIntArray(intArray);
|
||
|
||
|
||
// return str;
|
||
//}
|
||
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
public string GetValueAndDrawGridZhunKao(Bitmap img, VectorOfVectorOfPoint contours,
|
||
int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
{
|
||
//画网格
|
||
int[] intArray = GetTargetValuesOnlyOne(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
string str = "";
|
||
str += strText;
|
||
str += GetStringOfIntArray(intArray);
|
||
return str;
|
||
}
|
||
|
||
|
||
///// <summary>
|
||
///// 画出网格并返回填图结果
|
||
///// </summary>
|
||
///// <param name="img"></param>
|
||
///// <param name="contours"></param>
|
||
///// <param name="x_begin">左边距</param>
|
||
///// <param name="x_interval">方块长度</param>
|
||
///// <param name="x_num">方块数量</param>
|
||
///// <param name="y_begin">上边距</param>
|
||
///// <param name="y_interval">方块高度</param>
|
||
///// <param name="y_num">方块竖数量</param>
|
||
///// <param name="strText">输出文字</param>
|
||
///// <returns></returns>
|
||
//public string GetValueAndDrawGrid(ImageBox img, VectorOfVectorOfPoint contours,
|
||
// int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
//{
|
||
// //画网格
|
||
// //Mat src = new Image<Bgr, byte>(img.Image.Bitmap).Mat;
|
||
// //Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
|
||
// int[] intArray = GetTargetValues(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
// int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
|
||
// string str = "";
|
||
// //str += Environment.NewLine;//回车
|
||
// str += strText;
|
||
// if (maxValue >= 4 && maxValue <10)
|
||
// {
|
||
// str += GetStringOfIntArray(intArray);
|
||
// }
|
||
// else
|
||
// {
|
||
// if (maxValue >= 10)
|
||
// {
|
||
// str += GetStringOfIntArray(intArray, "ABCD");
|
||
// }
|
||
// else
|
||
// {
|
||
// str += GetStringOfIntArray(intArray, "ABCD");
|
||
// }
|
||
|
||
// }
|
||
|
||
// return str;
|
||
//}
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
public string GetValueAndDrawGrid(Bitmap img, VectorOfVectorOfPoint contours,
|
||
int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
{
|
||
|
||
//画网格
|
||
// Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
|
||
int[] intArray = GetTargetValuesOnlyOne(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
string str = "";
|
||
//str += Environment.NewLine;//回车
|
||
str += strText;
|
||
if (maxValue >= 4 && maxValue < 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
else
|
||
{
|
||
if (maxValue >= 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
else
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
public string GetValueAndDrawGrid_L(Bitmap img, VectorOfVectorOfPoint contours,
|
||
int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
{
|
||
//画网格
|
||
//Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
|
||
|
||
int[] intArray = GetTargetValues_L_only(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
|
||
string str = "";
|
||
//str += Environment.NewLine;//回车
|
||
str += strText;
|
||
if (maxValue >= 4 && maxValue < 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
else
|
||
{
|
||
if (maxValue >= 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
else
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
public string GetValueAndDrawGrid_Find(Bitmap img, VectorOfVectorOfPoint contours,
|
||
int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText, out Point pFindX)
|
||
{
|
||
//画网格
|
||
Point pFind;
|
||
int[] intArray = GetTargetGravityFind(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num, out pFind);
|
||
int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
pFindX = pFind;
|
||
string str = "";
|
||
//str += Environment.NewLine;//回车
|
||
str += strText;
|
||
if (maxValue >= 4 && maxValue < 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray);
|
||
}
|
||
else
|
||
{
|
||
if (maxValue >= 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEF");
|
||
}
|
||
else
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEF");
|
||
}
|
||
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
//public Mat GetDrawGrid(ImageBox img, VectorOfVectorOfPoint contours,
|
||
// int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
//{
|
||
// //画网格
|
||
// Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
// return mat_grid;
|
||
//}
|
||
|
||
public Mat GetDrawGrid(Bitmap img, VectorOfVectorOfPoint contours,
|
||
int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
{
|
||
//画网格
|
||
Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
return mat_grid;
|
||
}
|
||
|
||
|
||
///// <summary>
|
||
///// 画出网格并返回填图结果
|
||
///// </summary>
|
||
///// <param name="img"></param>
|
||
///// <param name="contours"></param>
|
||
///// <param name="x_begin">左边距</param>
|
||
///// <param name="x_interval">方块长度</param>
|
||
///// <param name="x_num">方块数量</param>
|
||
///// <param name="y_begin">上边距</param>
|
||
///// <param name="y_interval">方块高度</param>
|
||
///// <param name="y_num">方块竖数量</param>
|
||
///// <param name="strText">输出文字</param>
|
||
///// <returns></returns>
|
||
//public string GetValueAndDrawGridMore(ImageBox img, VectorOfVectorOfPoint contours,
|
||
// int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
//{
|
||
// //画网格
|
||
// //Mat src = new Image<Bgr, byte>(img.Image.Bitmap).Mat;
|
||
// //Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
|
||
// int[] intArray = GetTargetValues(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
// int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
|
||
// string str = "";
|
||
// str += strText;
|
||
// if (maxValue >= 7&& maxValue <10)
|
||
// {
|
||
// str += GetStringOfIntArray(intArray);
|
||
// }
|
||
// else
|
||
// {
|
||
// str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
// }
|
||
|
||
// return str;
|
||
//}
|
||
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
public string GetValueAndDrawGridMore(Bitmap img, VectorOfVectorOfPoint contours,
|
||
int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
{
|
||
|
||
//画网格
|
||
//Mat src = new Image<Bgr, byte>(img.Image.Bitmap).Mat;
|
||
//Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
|
||
int[] intArray = GetTargetValues(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
|
||
string str = "";
|
||
str += strText;
|
||
if (maxValue >= 7 && maxValue < 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray);
|
||
}
|
||
else
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 画出网格并返回填图结果
|
||
/// </summary>
|
||
/// <param name="img"></param>
|
||
/// <param name="contours"></param>
|
||
/// <param name="x_begin">左边距</param>
|
||
/// <param name="x_interval">方块长度</param>
|
||
/// <param name="x_num">方块数量</param>
|
||
/// <param name="y_begin">上边距</param>
|
||
/// <param name="y_interval">方块高度</param>
|
||
/// <param name="y_num">方块竖数量</param>
|
||
/// <param name="strText">输出文字</param>
|
||
/// <returns></returns>
|
||
public string GetValueAndDrawGridMoreL(Bitmap img, VectorOfVectorOfPoint contours,
|
||
int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num, string strText)
|
||
{
|
||
//画网格
|
||
//Mat mat_grid = DrawGridByXY(img, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
|
||
int[] intArray = GetTargetValues_L(contours, x_begin, x_interval, x_num, y_begin, y_interval, y_num);
|
||
int maxValue = GetMaxValueOfArray(intArray);//数组最大值
|
||
|
||
string str = "";
|
||
str += strText;
|
||
if (maxValue >= 7 && maxValue < 10)
|
||
{
|
||
str += GetStringOfIntArray(intArray);
|
||
}
|
||
else
|
||
{
|
||
str += GetStringOfIntArray(intArray, "ABCDEFG");
|
||
}
|
||
return str;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 计算轮廓中心点坐标
|
||
/// </summary>
|
||
/// <param name="selected_contours">要计算中心点的轮廓</param>
|
||
/// <returns></returns>
|
||
public Point[] GetGravityOfContours(VectorOfVectorOfPoint selected_contours)
|
||
{
|
||
int ksize = selected_contours.Size;
|
||
|
||
double[] m00 = new double[ksize];
|
||
double[] m01 = new double[ksize];
|
||
double[] m10 = new double[ksize];
|
||
Point[] gravity = new Point[ksize];//用于存储轮廓中心点坐标
|
||
MCvMoments[] moments = new MCvMoments[ksize];
|
||
|
||
for (int i = 0; i < ksize; i++)
|
||
{
|
||
VectorOfPoint contour = selected_contours[i];
|
||
//计算当前轮廓的矩
|
||
moments[i] = CvInvoke.Moments(contour, false);
|
||
|
||
|
||
m00[i] = moments[i].M00;
|
||
m01[i] = moments[i].M01;
|
||
m10[i] = moments[i].M10;
|
||
int x = Convert.ToInt32(m10[i] / m00[i]);//计算当前轮廓中心点坐标
|
||
int y = Convert.ToInt32(m01[i] / m00[i]);
|
||
gravity[i] = new Point(x, y);
|
||
|
||
}
|
||
return gravity;
|
||
}
|
||
///// <summary>
|
||
///// 根据给定XY初始坐标、间距、数量画网格
|
||
///// </summary>
|
||
///// <param name="mat"></param>
|
||
///// <param name="x"></param>
|
||
///// <param name="x_interval"></param>
|
||
///// <param name="x_num"></param>
|
||
///// <param name="y"></param>
|
||
///// <param name="y_interval"></param>
|
||
///// <param name="y_num"></param>
|
||
///// <returns></returns>
|
||
//public Mat DrawGridByXY(ImageBox img, int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num)
|
||
//{
|
||
|
||
|
||
// Mat src = new Image<Bgr, byte>(img.Image.Bitmap).Mat;
|
||
|
||
// //转换颜色空间
|
||
// Mat mat_color = new Mat();
|
||
// if (src.NumberOfChannels == 1)
|
||
// CvInvoke.CvtColor(src, mat_color, Emgu.CV.CvEnum.ColorConversion.Gray2Bgr);
|
||
// else
|
||
// mat_color = src;
|
||
|
||
// for (int i = 0; i <= x_num; i++)
|
||
// {
|
||
// //先画竖线
|
||
// Point p1 = new Point(x_begin + x_interval * i, y_begin);
|
||
// Point p2 = new Point(x_begin + x_interval * i, y_begin + y_interval * y_num);
|
||
// CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 1);
|
||
// }
|
||
|
||
// for (int i = 0; i <= y_num; i++)
|
||
// {
|
||
// //再画横线
|
||
// Point p1 = new Point(x_begin, y_begin + y_interval * i);
|
||
// Point p2 = new Point(x_begin + x_interval * x_num, y_begin + y_interval * i);
|
||
// CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 1);
|
||
// }
|
||
|
||
// img.Image = mat_color;
|
||
|
||
|
||
// return mat_color;
|
||
//}
|
||
|
||
/// <summary>
|
||
/// 根据给定XY初始坐标、间距、数量画网格
|
||
/// </summary>
|
||
/// <param name="mat"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="x_interval"></param>
|
||
/// <param name="x_num"></param>
|
||
/// <param name="y"></param>
|
||
/// <param name="y_interval"></param>
|
||
/// <param name="y_num"></param>
|
||
/// <returns></returns>
|
||
public Mat DrawGridByXY(Bitmap img, int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num)
|
||
{
|
||
|
||
|
||
Mat src = new Image<Bgr, byte>(img).Mat;
|
||
|
||
//转换颜色空间
|
||
Mat mat_color = new Mat();
|
||
if (src.NumberOfChannels == 1)
|
||
CvInvoke.CvtColor(src, mat_color, Emgu.CV.CvEnum.ColorConversion.Gray2Bgr);
|
||
else
|
||
mat_color = src;
|
||
|
||
for (int i = 0; i <= x_num; i++)
|
||
{
|
||
//先画竖线
|
||
Point p1 = new Point(x_begin + x_interval * i, y_begin);
|
||
Point p2 = new Point(x_begin + x_interval * i, y_begin + y_interval * y_num);
|
||
CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 1);
|
||
}
|
||
|
||
for (int i = 0; i <= y_num; i++)
|
||
{
|
||
//再画横线
|
||
Point p1 = new Point(x_begin, y_begin + y_interval * i);
|
||
Point p2 = new Point(x_begin + x_interval * x_num, y_begin + y_interval * i);
|
||
CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 1);
|
||
}
|
||
|
||
//img.Image = mat_color;
|
||
|
||
|
||
return mat_color;
|
||
}
|
||
|
||
public Mat DrawGridByXY(Mat img, int x_begin, int x_interval, int x_num, int y_begin, int y_interval, int y_num)
|
||
{
|
||
|
||
|
||
Mat src = img;
|
||
|
||
//转换颜色空间
|
||
Mat mat_color = new Mat();
|
||
if (src.NumberOfChannels == 1)
|
||
CvInvoke.CvtColor(src, mat_color, Emgu.CV.CvEnum.ColorConversion.Gray2Bgr);
|
||
else
|
||
mat_color = src;
|
||
|
||
for (int i = 0; i <= x_num; i++)
|
||
{
|
||
//先画竖线
|
||
Point p1 = new Point(x_begin + x_interval * i, y_begin);
|
||
Point p2 = new Point(x_begin + x_interval * i, y_begin + y_interval * y_num);
|
||
CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 1);
|
||
}
|
||
|
||
for (int i = 0; i <= y_num; i++)
|
||
{
|
||
//再画横线
|
||
Point p1 = new Point(x_begin, y_begin + y_interval * i);
|
||
Point p2 = new Point(x_begin + x_interval * x_num, y_begin + y_interval * i);
|
||
CvInvoke.Line(mat_color, p1, p2, new MCvScalar(0, 0, 255), 1);
|
||
}
|
||
|
||
//img.Image = mat_color;
|
||
|
||
|
||
return mat_color;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 画出给定轮廓
|
||
/// </summary>
|
||
/// <param name="mat"></param>
|
||
/// <param name="contours"></param>
|
||
/// <returns></returns>
|
||
public Mat DrawContours(Mat mat, VectorOfVectorOfPoint contours)
|
||
{
|
||
//转换颜色空间
|
||
Mat mat_color = new Mat();
|
||
CvInvoke.CvtColor(mat, mat_color, Emgu.CV.CvEnum.ColorConversion.Gray2Bgr);
|
||
|
||
CvInvoke.DrawContours(mat_color, contours, -1, new MCvScalar(255, 0, 0), 2);
|
||
return mat_color;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 拼接给定int数组内容,并返回拼接后字符串
|
||
/// </summary>
|
||
/// <param name="arr"></param>
|
||
/// <returns></returns>
|
||
public string GetStringOfIntArray(int[] arr)
|
||
{
|
||
string str = "";
|
||
foreach (int a in arr)
|
||
{
|
||
str += a.ToString() + "";
|
||
}
|
||
return str;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 拼接给定int数组内容,并返回拼接后字符串
|
||
/// </summary>
|
||
/// <param name="arr"></param>
|
||
/// <returns></returns>
|
||
public string GetStringOfIntArray(int[] arr, string ss = "ABCD")
|
||
{
|
||
string str = "";
|
||
//char[] ch = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
|
||
char[] ch = ss.ToCharArray();
|
||
foreach (int a in arr)
|
||
{
|
||
///
|
||
if (a >= 10)
|
||
{
|
||
string x = a.ToString();
|
||
char[] cc = x.ToArray();
|
||
|
||
int[] result = new int[cc.Length];
|
||
|
||
for (int i = 0; i < cc.Length; i++)
|
||
{
|
||
result[i] = Convert.ToInt32(x.Substring(i, 1));
|
||
}
|
||
Array.Sort(result);
|
||
|
||
int[] finalResult = result;
|
||
for (int j = 0; j < finalResult.Length; j++)
|
||
{
|
||
if (finalResult[j] == -1)
|
||
{
|
||
str += "null";
|
||
}
|
||
else
|
||
{
|
||
str += ch[finalResult[j]];
|
||
}
|
||
}
|
||
str += " ";
|
||
}
|
||
else
|
||
{
|
||
if (a == -1)
|
||
{
|
||
str += "null ";//未识别时,标示为空
|
||
}
|
||
else
|
||
{
|
||
str += ch[a] + " ";
|
||
}
|
||
|
||
}
|
||
}
|
||
return str;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 获取一维int数组中最大值
|
||
/// </summary>
|
||
/// <param name="arr"></param>
|
||
/// <returns></returns>
|
||
public int GetMaxValueOfArray(int[] arr)
|
||
{
|
||
int[] dst = new int[arr.Length];
|
||
Array.Copy(arr, dst, arr.Length);//深度复制数组,防止排序对原数组产生影响
|
||
Array.Sort(dst);//数组排序
|
||
int maxValue = dst[arr.Length - 1];//数组最大值
|
||
return maxValue;
|
||
}
|
||
/// <summary>
|
||
/// 显示图像,并等待按下任意按键后继续
|
||
/// </summary>
|
||
/// <param name="title"></param>
|
||
/// <param name="mat"></param>
|
||
/// <param name="zoomRatio"></param>
|
||
public void ShowMatWaitKey(string title, Mat mat, double zoomRatio)
|
||
{
|
||
CvInvoke.Resize(mat, mat, new Size(), zoomRatio, zoomRatio, Inter.Cubic);
|
||
CvInvoke.Imshow(title, mat);
|
||
CvInvoke.WaitKey(0);
|
||
}
|
||
|
||
|
||
public Bitmap RotateByOrientation(Bitmap bitmap)
|
||
{
|
||
// 获取图片的方向信息并根据方向调整图片
|
||
if (bitmap.PropertyIdList.Contains(0x0112))
|
||
{
|
||
var orientation = (int)bitmap.GetPropertyItem(0x0112).Value[0];
|
||
switch (orientation)
|
||
{
|
||
case 2:
|
||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
||
break;
|
||
case 3:
|
||
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
|
||
break;
|
||
case 4:
|
||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||
break;
|
||
case 5:
|
||
bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
|
||
break;
|
||
case 6:
|
||
bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
|
||
break;
|
||
case 7:
|
||
bitmap.RotateFlip(RotateFlipType.Rotate270FlipX);
|
||
break;
|
||
case 8:
|
||
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
|
||
break;
|
||
}
|
||
}
|
||
return bitmap;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 过滤红色
|
||
/// </summary>
|
||
/// <param name="bitmap"></param>
|
||
/// <returns></returns>
|
||
public Bitmap FilterRed(Bitmap bitmap)
|
||
{
|
||
CommonUse commonUse = new CommonUse();
|
||
|
||
Image<Bgr, byte> src = new Image<Bgr, byte>(bitmap);
|
||
|
||
Mat gray = new Mat();
|
||
CvInvoke.CvtColor(src, gray, ColorConversion.Bgr2Gray);
|
||
|
||
|
||
VectorOfMat channels = new VectorOfMat();
|
||
CvInvoke.Split(src, channels);
|
||
if (channels.Size < 3)
|
||
{
|
||
return bitmap;
|
||
}
|
||
Mat red = channels[2];
|
||
//commonUse.ShowMatWaitKey("red", red, 0.5);
|
||
|
||
Mat redBinary = new Mat();
|
||
CvInvoke.Threshold(red, redBinary, 150, 255, ThresholdType.Binary);
|
||
//commonUse.ShowMatWaitKey("red+binary", redBinary, 0.5);
|
||
|
||
//Mat redDilate = new Mat();
|
||
//Mat kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(2, 2), new Point(-1, -1));
|
||
//CvInvoke.Dilate(redBinary, redDilate, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar(0, 0, 0));
|
||
|
||
//kernel = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(2, 2), new Point(-1, -1));
|
||
//CvInvoke.MorphologyEx(redBinary, redDilate, MorphOp.Open, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar(0, 0, 0));
|
||
//commonUse.ShowMatWaitKey("redDilate", redDilate, 0.5);
|
||
|
||
return redBinary.Bitmap;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
public class ZhuguantiList
|
||
{
|
||
public int QuestionSmallNum
|
||
{
|
||
get; set;
|
||
}
|
||
public Bitmap btm
|
||
{
|
||
get; set;
|
||
}
|
||
public string num
|
||
{
|
||
get; set;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
public class otherBitmaplist
|
||
{
|
||
public Bitmap btm
|
||
{
|
||
get; set;
|
||
}
|
||
public string Text
|
||
{
|
||
get; set;
|
||
}
|
||
} |