流程
/// <summary>
/// 寻找图像中的轮廓
/// </summary>
/// <param name="resMat">原图</param>
/// <param name="maxArea">最大面积</param>
/// <param name="minArea">最小面积</param>
/// <param name="minWidth">最小宽度</param>
/// <param name="maxHeight">最大高度</param>
/// <returns></returns>
private static List<Point[]> FindImgLunKuo(Mat resMat, int maxArea, int minArea, int minWidth, int maxHeight)
{
// 读取灰度图
Mat grayMat = new Mat();
Cv2.CvtColor(resMat, grayMat, ColorConversionCodes.BGR2GRAY);
// 二值化
Mat binary = new Mat();
Cv2.Threshold(grayMat, binary, 127, 255, ThresholdTypes.Binary);//转换为二值图像
//binary.SaveImage(@"C:\Users\Administrator\Desktop\桌面文件夹\images\scanfile\题卡合一\0227-1\binary1.jpg");
// 图片反色
Cv2.BitwiseNot(binary, binary);
//binary.SaveImage(@"C:\Users\Administrator\Desktop\桌面文件夹\images\scanfile\题卡合一\0227-1\binary2.jpg");
// 腐蚀去除较细的线条
Mat result = new Mat();
InputArray kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5), new Point(-1, -1));
Cv2.Erode(binary, result, kernel);
//result.SaveImage(@"C:\Users\Administrator\Desktop\桌面文件夹\images\scanfile\题卡合一\0227-1\bitnot.jpg");
// 边缘检测
Mat cyMat = new Mat();
Cv2.Canny(result, cyMat, 50, 150);
//cyMat.SaveImage(@"C:\Users\Administrator\Desktop\桌面文件夹\images\scanfile\题卡合一\0227-1\cnn.jpg");
// 过滤出合适点的轮廓
List<Point[]> resShaixuan = new List<Point[]>();
// 寻找轮廓
Cv2.FindContours(cyMat, out Point[][] contours, out HierarchyIndex[] hierarchies, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new Point());
//int j = 0;
for (int i = 0; i < contours.Length; i++)
{
// 检测点是否为 0 0
bool flag = CheckZeroPoint(contours[i]);
if (!flag)
{
continue;
}
// 连接最小矩形 过滤出合适面积的数组
RotatedRect rotatedRect = Cv2.MinAreaRect(contours[i]);
Point2f[] point2s = Cv2.BoxPoints(rotatedRect);
List<float> point2fXList = new List<float>();
List<float> point2fYList = new List<float>();
for (int j = point2s.Length - 1; j >= 0; j--)
{
//Console.WriteLine("point2s:" + j + "==" + point2s[j]);
point2fXList.Add(point2s[j].X);
point2fYList.Add(point2s[j].Y);
}
point2fXList.Sort();// 升序排序
point2fYList.Sort();// 升序排序
// 过滤宽度过小
if (point2fXList[point2fXList.Count - 1] - point2fXList[0] < minWidth)
{
continue;
}
// 过滤高度过高
if (point2fYList[point2fYList.Count - 1] - point2fYList[0] > maxHeight)
{
continue;
}
// 过滤边缘
if (Math.Abs(resMat.Width - point2fXList[point2fXList.Count - 1]) < 3 || Math.Abs(resMat.Height - point2fXList[point2fYList.Count - 1]) < 3)
{
continue;
}
// 面积过滤
Rect rect = rotatedRect.BoundingRect();
int recWidth = rect.Width;
int recHeight = rect.Height;
int mianji = recWidth * recHeight;
if (mianji > minArea && mianji < maxArea)
{
Console.WriteLine("mianji == " + mianji);
resShaixuan.Add(contours[i]);
// 根据点画线
//Cv2.DrawContours(resMat, resShaixuan, -1, new Scalar(0, 0, 255), 3, LineTypes.Link4);
//resMat.SaveImage(@"C:\Users\Administrator\Desktop\桌面文件夹\images\scanfile\题卡合一\0227-1\draw.jpg");
break;
}
}
return resShaixuan;
}