//预测图片类型是否正确 public static PlateCategory Test(Mat matTest) { try { if (IsReady == false || svm == null) { throw new Exception("训练数据为空,请重新训练?车牌类型识别或加载数据"); } PlateCategory result = PlateCategory.非车牌; if (IsReady == false || svm == null) { return(result); } //¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ Mat matTestGray = matTest.CvtColor(ColorConversionCodes.BGR2GRAY); //之后记得改为0-255 Mat matTestDst = matTestGray.Threshold(0, 225, ThresholdTypes.Otsu | ThresholdTypes.Binary); float[] descriptor = ComputeHogDescriptors(matTestDst); Mat testDescriptor = Mat.Zeros(1, descriptor.Length, MatType.CV_32FC1); for (int index = 0; index < descriptor.Length; index++) { testDescriptor.Set <float>(0, index, descriptor[index]); } float predict = svm.Predict(testDescriptor); result = (PlateCategory)((int)predict); return(result); } catch (Exception ex) { throw ex; } }
//测试 public static PlateCategory Test(Mat matTest) { try { if (IsReady == false || svm == null) { throw new Exception("训练数据为空,请重新训练⻋牌类型识别或加载数据"); } PlateCategory result = PlateCategory.非车牌; if (IsReady == false || svm == null) { return(result); } float[] descriptor = ComputeHogDescriptors(matTest); Mat testDescriptor = TypeConvert.Float2Mat(descriptor); float predict = svm.Predict(testDescriptor); result = (PlateCategory)((int)predict); return(result); } catch (Exception ex) { throw ex; } }
// 字符保存 public static void SaveCharSample(Mat charMat, PlateCategory plateCate, string libPath, string shortFileNameNoExt) { string fileName = string.Format(@"{0}\Mychars\{1}\{2}.jpg", libPath, plateCate, shortFileNameNoExt); charMat = charMat.Resize(WIN_SIZE); charMat.SaveImage(fileName); }
// 保存图片样本 public static void SavePlateSample(Mat matPlate, PlateCategory plateCategory, string libPath, string shortFileNameNoExt) { DateTime now = DateTime.Now; string fileName = string.Format(@"{0}\plates\{1}\{2}.jpg", libPath, plateCategory, shortFileNameNoExt); matPlate.SaveImage(fileName); }
public PlateImage(string fileName, string name, PlateCategory plateCategory, OpenCvSharp.Size matSize) { this.FileName = fileName; this.Name = name; this.PlateCategory = plateCategory; this.MatSize = matSize; }
//保存图片样本 public static void SavePlateSample(Mat matPlate, PlateCategory plateCategory, string libPath) { DateTime now = DateTime.Now; string name = string.Format("{0}-{1:00}-{2:00}-{3:00}-{4:00}-{5:00}-{6:000000}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, random.Next(100000)); string fileName = string.Format(@"{0}\plates\{1}\{2}.jpg", libPath, plateCategory, name); matPlate.SaveImage(fileName); }
public PlateInfo(PlateCategory plateCategory, Rect originalRect, Mat originalMat, List <CharInfo> charInfos, PlateLocateMethod plateLocateMethod) { this.PlateCategory = plateCategory; this.OriginalRect = originalRect; this.OriginalMat = originalMat; this.CharInfos = charInfos; this.PlateLocateMethod = plateLocateMethod; }
public static PlateCategory Test(Mat matPlate) { float[] hog = GetHog(matPlate); Mat matTest = new Mat(1, hog.Length, MatType.CV_32FC1); for (int i = 0; i < hog.Length; i++) { matTest.Set <float>(0, i, hog[i]); } PlateCategory result = (PlateCategory)((int)svm.Predict(matTest)); return(result); }
private void tvTest_AfterSelect(object sender, TreeViewEventArgs e) { if (e.Node.Level == 0) { return; } string fileName = e.Node.Tag as string; if (fileName == null) { return; } Mat matPreview = Cv2.ImRead(fileName); this.picImage.Image = matPreview.ToBitmap(); PlateCategory category = Plate_SVM.Test(matPreview); this.txtinfo.AppendText(string.Format("\r\n预测结果:{0}\r\n", category)); }
public static List <PlateCategory> TestList(List <Mat> matPlateList) { List <PlateCategory> resultList = new List <PlateCategory>(); PlateCategory result = 0; foreach (var matPlate in matPlateList) { float[] hog = GetHog(matPlate); Mat matTest = new Mat(1, hog.Length, MatType.CV_32FC1); for (int i = 0; i < hog.Length; i++) { matTest.Set <float>(0, i, hog[i]); } result = (PlateCategory)((int)svm.Predict(matTest)); resultList.Add(result); } return(resultList); }
public static List <PlateInfo> RecogPlateAndChar(Mat matSource) { List <PlateInfo> PlateInfoList = PlateRecognition_V3.Recognite(matSource); if (PlateInfoList.Count == 0) { PlateCategory PlateCategory = PlateCategory.非车牌; Rect OriginalRect = new Rect(); Mat OriginalMatnew = new Mat(); PlateLocateMethod PlateLocateMethod = PlateLocateMethod.未知; List <CharInfo> CharInfos = null; PlateInfo noPlateInfo = new PlateInfo(PlateCategory, OriginalRect, OriginalMatnew, CharInfos, PlateLocateMethod); PlateInfoList.Add(noPlateInfo); return(PlateInfoList); } else { return(PlateInfoList); } }
/// <summary> /// 开始训练 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { if (this.samplePath == "") { return; } List <PlateInfo> plateSamples = new List <PlateInfo>(); string[] subDirectories = Directory.GetDirectories(this.samplePath); for (int index = 0; index < subDirectories.Length; index++) { string subDirectory = subDirectories[index]; string shortDirectory = subDirectory.Substring(subDirectory.LastIndexOf(@"\") + 1); PlateCategory category = (PlateCategory)Enum.Parse(typeof(PlateCategory), shortDirectory); string[] fileNames = Directory.GetFiles(subDirectory, "*.jpg"); for (int i = 0; i < fileNames.Length; i++) { string fileName = fileNames[i]; this.txtinfo.AppendText(string.Format("{0} 类型:{1}\r\n", fileName, category)); Mat matPlate = Cv2.ImRead(fileName); PlateInfo plateInfo = new PlateInfo(); plateInfo.PlateMat = matPlate; plateInfo.Category = category; plateSamples.Add(plateInfo); } } //将样本的元数据转化为SVM的样品数据和标签数据 Mat trainData = new Mat(); Mat trainLabel = new Mat(plateSamples.Count, 1, MatType.CV_32SC1); for (int index = 0; index < plateSamples.Count; index++) { PlateInfo plateInfo = plateSamples[index]; float[] hog = Plate_SVM.GetHog(plateInfo.PlateMat); if (index == 0) { trainData = Mat.Zeros(plateSamples.Count, hog.Length, MatType.CV_32FC1); } for (int colIndex = 0; colIndex < hog.Length; colIndex++) { trainData.Set <float>(index, colIndex, hog[colIndex]); } trainLabel.Set <int>(index, 0, (int)plateInfo.Category); this.txtinfo.AppendText(hog.Length.ToString() + "\r\n"); } Plate_SVM.Train(trainData, trainLabel); this.txtinfo.AppendText("训练已完成\r\n"); }
public static List <PlateInfo> LocatePlatesForAutoSample(Mat matSource, out Mat matProcess, int blur_Size = 5, int sobel_Scale = 1, int sobel_Delta = 0, int sobel_X_Weight = 1, int sobel_Y_Weight = 0, int morph_Size_Width = 17, int morph_Size_Height = 3, int minWidth = 60, int maxWidth = 180, int minHeight = 18, int maxHeight = 80, float minRatio = 0.15f, float maxRatio = 0.70f) { List <PlateInfo> plateInfos = new List <PlateInfo>(); Mat gray = null; Mat blur = null; if (matSource.Empty() || matSource.Rows == 0 || matSource.Cols == 0) { matProcess = new Mat(0, 0, MatType.CV_8UC1); return(plateInfos); } //灰度图 gray = matSource.CvtColor(ColorConversionCodes.BGR2GRAY); //高斯模糊图 blur = gray.GaussianBlur(new OpenCvSharp.Size(blur_Size, blur_Size), 0, 0, BorderTypes.Default); //HSV图 Mat hsv = matSource.CvtColor(ColorConversionCodes.BGR2HSV); //将HSV图分成H、S、V通道图 Mat[] hsvSplits = hsv.Split(); hsvSplits[2] = hsvSplits[2].EqualizeHist(); Mat hsvEqualizeHist = new Mat(); //合并通道图 Cv2.Merge(hsvSplits, hsvEqualizeHist); //提取蓝色 Scalar blueStart = new Scalar(100, 70, 70); Scalar blueEnd = new Scalar(140, 255, 255); Mat blue = hsvEqualizeHist.InRange(blueStart, blueEnd); //提取黄色 Scalar yellowStart = new Scalar(15, 70, 70); Scalar yellowEnd = new Scalar(40, 255, 255); Mat yellow = hsvEqualizeHist.InRange(yellowStart, yellowEnd); Mat add = blue + yellow; //二值化 Mat threshold = add.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(morph_Size_Width, morph_Size_Height)); //闭操作 Mat threshold_Close = threshold.MorphologyEx(MorphTypes.Close, element); Mat element_Erode = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3)); Mat threshold_Erode = threshold_Close.Erode(element_Erode); matProcess = threshold_Erode; OpenCvSharp.Point[][] contours = null; HierarchyIndex[] hierarchys = null; Cv2.FindContours(threshold_Erode, out contours, out hierarchys, RetrievalModes.External, ContourApproximationModes.ApproxNone); int isPlateCount = 0; for (int index = 0; index < contours.Length; index++) { RotatedRect rotatedRect = Cv2.MinAreaRect(contours[index]); Rect rectROI = Cv2.BoundingRect(contours[index]); if (VerifyPlateSize(rectROI.Size, minWidth, maxWidth, minHeight, maxHeight, minRatio, maxRatio)) { Mat matROI = matSource.SubMat(rectROI); PlateCategory plateCategory = PlateCategory_SVM.Test(matROI); if (plateCategory != PlateCategory.非车牌) { isPlateCount++; } PlateInfo plateInfo = new PlateInfo(); plateInfo.RotatedRect = rotatedRect; plateInfo.OriginalRect = rectROI; plateInfo.OriginalMat = matROI; plateInfo.PlateCategory = plateCategory; plateInfo.PlateLocateMethod = PlateLocateMethod.颜色法; plateInfos.Add(plateInfo); } } if (isPlateCount > 0) { return(plateInfos); } blur = matSource.GaussianBlur(new OpenCvSharp.Size(blur_Size, blur_Size), 0, 0, BorderTypes.Default); gray = blur.CvtColor(ColorConversionCodes.BGR2GRAY); // 对图像进行Sobel 运算,得到的是图像的一阶水平方向导数。 // Generate grad_x and grad_y MatType ddepth = MatType.CV_16S; Mat grad_x = gray.Sobel(ddepth, 1, 0, 3, sobel_Scale, sobel_Delta, BorderTypes.Default); Mat abs_grad_x = grad_x.ConvertScaleAbs(); Mat grad_y = gray.Sobel(ddepth, 0, 1, 3, sobel_Scale, sobel_Delta, BorderTypes.Default); Mat abs_grad_y = grad_y.ConvertScaleAbs(); Mat grad = new Mat(); Cv2.AddWeighted(abs_grad_x, sobel_X_Weight, abs_grad_y, sobel_Y_Weight, 0, grad); // 对图像进行二值化。将灰度图像(每个像素点有256 个取值可能)转化为二值图像(每个像素点仅有1 和0 两个取值可能)。 threshold = grad.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); // 使用闭操作。对图像进?行行闭操作以后,可以看到车牌区域被连接成一个矩形装的区域。 element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(morph_Size_Width, morph_Size_Height)); threshold_Close = threshold.MorphologyEx(MorphTypes.Close, element); element_Erode = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(5, 5)); threshold_Erode = threshold_Close.Erode(element_Erode); matProcess = threshold_Erode; // Find 轮廓 of possibles plates 求轮廓。求出图中所有的轮廓。这个算法会把全图的轮廓都计算出来,因此要进? 行行筛选。 contours = null; hierarchys = null; Cv2.FindContours(threshold_Erode, out contours, out hierarchys, RetrievalModes.External, ContourApproximationModes.ApproxNone); // 筛选。对轮廓求最?小外接矩形,然后验证,不不满?足条件的淘汰。 for (int index = 0; index < contours.Length; index++) { Rect rectROI = Cv2.BoundingRect(contours[index]); if (VerifyPlateSize(rectROI.Size, minWidth, maxWidth, minHeight, maxHeight, minRatio, maxRatio)) { RotatedRect rotatedRect = Cv2.MinAreaRect(contours[index]); Mat matROI = matSource.SubMat(rectROI); PlateCategory plateCategory = PlateCategory_SVM.Test(matROI); PlateInfo plateInfo = new PlateInfo(); plateInfo.RotatedRect = rotatedRect; plateInfo.OriginalRect = rectROI; plateInfo.OriginalMat = matROI; plateInfo.PlateCategory = plateCategory; plateInfo.PlateLocateMethod = PlateLocateMethod.Sobel法; plateInfos.Add(plateInfo); } } return(plateInfos); }
private static List <PlateInfo> LocatePlatesBySobel(Mat matSource, int blur_Size = 5, int sobel_Scale = 1, int sobel_Delta = 0, int sobel_X_Weight = 1, int sobel_Y_Weight = 0, int morph_Size_Width = 17, int morph_Size_Height = 3, int minWidth = 60, int maxWidth = 180, int minHeight = 18, int maxHeight = 80, float minRatio = 0.15f, float maxRatio = 0.70f) { List <PlateInfo> plateInfos = new List <PlateInfo>(); if (matSource.Empty()) { return(plateInfos); } Mat blur = null; Mat gray = null; blur = matSource.GaussianBlur(new OpenCvSharp.Size(blur_Size, blur_Size), 0, 0, BorderTypes.Default); gray = blur.CvtColor(ColorConversionCodes.BGR2GRAY); // 对图像进行Sobel 运算,得到的是图像的一阶水平方向导数。 // Generate grad_x and grad_y MatType ddepth = MatType.CV_16S; Mat grad_x = gray.Sobel(ddepth, 1, 0, 3, sobel_Scale, sobel_Delta, BorderTypes.Default); Mat abs_grad_x = grad_x.ConvertScaleAbs(); Mat grad_y = gray.Sobel(ddepth, 0, 1, 3, sobel_Scale, sobel_Delta, BorderTypes.Default); Mat abs_grad_y = grad_y.ConvertScaleAbs(); Mat grad = new Mat(); Cv2.AddWeighted(abs_grad_x, sobel_X_Weight, abs_grad_y, sobel_Y_Weight, 0, grad); // 对图像进行二值化。将灰度图像(每个像素点有256 个取值可能)转化为二值图像(每个像素点仅有1 和0 两个取值可能)。 Mat threshold = grad.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); // 使用闭操作。对图像进行闭操作以后,可以看到车牌区域被连接成一个矩形装的区域。 Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(morph_Size_Width, morph_Size_Height)); Mat threshold_Close = threshold.MorphologyEx(MorphTypes.Close, element); Mat element_Erode = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(5, 5)); Mat threshold_Erode = threshold_Close.Erode(element_Erode); // Find 轮廓 of possibles plates 求轮廓。求出图中所有的轮廓。这个算法会把全图的轮廓都计算出来,因此要进行筛选。 OpenCvSharp.Point[][] contours = null; HierarchyIndex[] hierarchys = null; Cv2.FindContours(threshold_Erode, out contours, out hierarchys, RetrievalModes.External, ContourApproximationModes.ApproxNone); // 筛选。对轮廓求最小外接矩形,然后验证,不满足条件的淘汰。 for (int index = 0; index < contours.Length; index++) { Rect rectROI = Cv2.BoundingRect(contours[index]); if (VerifyPlateSize(rectROI.Size, minWidth, maxWidth, minHeight, maxHeight, minRatio, maxRatio)) { Mat matROI = matSource.SubMat(rectROI); PlateCategory plateCategory = PlateCategory_SVM.Test(matROI); if (plateCategory == PlateCategory.非车牌) { continue; } PlateInfo plateInfo = new PlateInfo(); plateInfo.OriginalRect = rectROI; plateInfo.OriginalMat = matROI; plateInfo.PlateCategory = plateCategory; plateInfo.PlateLocateMethod = PlateLocateMethod.Sobel法; plateInfos.Add(plateInfo); } } return(plateInfos); }
//颜色法 private static List <PlateInfo> LocatePlatesByColor(Mat matSource, int blur_Size = 5, int morph_Size_Width = 17, int morph_Size_Height = 3, int minWidth = 60, int maxWidth = 180, int minHeight = 18, int maxHeight = 80, float minRatio = 0.15f, float maxRatio = 0.70f) { List <PlateInfo> plateInfos = new List <PlateInfo>(); if (matSource.Empty()) { return(plateInfos); } Mat hsv = matSource.CvtColor(ColorConversionCodes.BGR2HSV); Mat[] hsvSplits = hsv.Split(); hsvSplits[2] = hsvSplits[2].EqualizeHist(); Mat hsvEqualizeHist = new Mat(); Cv2.Merge(hsvSplits, hsvEqualizeHist); Scalar blueStart = new Scalar(100, 70, 70); Scalar blueEnd = new Scalar(140, 255, 255); Mat blue = hsvEqualizeHist.InRange(blueStart, blueEnd); Scalar yellowStart = new Scalar(15, 70, 70); Scalar yellowEnd = new Scalar(40, 255, 255); Mat yellow = hsvEqualizeHist.InRange(yellowStart, yellowEnd); Mat add = blue + yellow; Mat threshold = add.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(morph_Size_Width, morph_Size_Height)); Mat threshold_Close = threshold.MorphologyEx(MorphTypes.Close, element); Mat element_Erode = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3)); Mat threshold_Erode = threshold_Close.Erode(element_Erode); OpenCvSharp.Point[][] contours = null; HierarchyIndex[] hierarchys = null; Cv2.FindContours(threshold_Erode, out contours, out hierarchys, RetrievalModes.External, ContourApproximationModes.ApproxNone); for (int index = 0; index < contours.Length; index++) { Rect rectROI = Cv2.BoundingRect(contours[index]); if (VerifyPlateSize(rectROI.Size, minWidth, maxWidth, minHeight, maxHeight, minRatio, maxRatio)) { Mat matROI = matSource.SubMat(rectROI); PlateCategory plateCategory = PlateCategory_SVM.Test(matROI); if (plateCategory == PlateCategory.非车牌) { continue; } PlateInfo plateInfo = new PlateInfo(); plateInfo.OriginalRect = rectROI; plateInfo.OriginalMat = matROI; plateInfo.PlateCategory = plateCategory; plateInfo.PlateLocateMethod = PlateLocateMethod.颜色法; plateInfos.Add(plateInfo); } } return(plateInfos); }
public static List <Mat> carCharSplit(Mat matPlate) { Mat hsvmat = matPlate.CvtColor(ColorConversionCodes.BGR2HSV); Mat[] hsv = hsvmat.Split(); Mat h = hsv[0]; Mat s = hsv[1]; Mat v = hsv[2]; for (int i = 0; i < hsvmat.Rows; i++) { for (int j = 0; j < hsvmat.Cols; j++) { byte hvalue = h.At <byte>(i, j); //////////////////h通道/-///////////////////// // Console.WriteLine(hvalue + ":h"); byte svalue = s.At <byte>(i, j); //////////////////s通道/-///////////////////// byte vvalue = v.At <byte>(i, j); //////////////////v通道/-///////////////////// // printf("x=%d,y=%d,HSV: H=%d,S=%d,V=%d\n",i,j,hvalue,svalue,vvalue); if ((hvalue > 80 && hvalue < 130) && (svalue > 43 && svalue < 220) && (vvalue > 46 && vvalue < 255)) //hsv图像在蓝色区域里 { //蓝色+1 bluenum++; } else if ((hvalue > 11 && hvalue < 34) && (svalue > 43 && svalue < 255) && (vvalue > 46 && vvalue < 255))//hsv在黄色区域里 { //黄色+1 yellownum++; } else if ((hvalue > 0 && hvalue < 180) && (svalue > 0 && svalue < 255) && (vvalue > 0 && vvalue < 46))//hsv在黑色区域里 { blacknum++; //黑色+1 } else if ((hvalue > 0 && hvalue < 180) && (svalue > 0 && svalue < 30) && (vvalue > 46 && vvalue < 220))//hsv在白色区域里 { //白色+1 whitenum++; } else if ((hvalue > 60 && hvalue < 90) && (svalue > 43 && svalue < 255) && (vvalue > 46 && vvalue < 255))//hsv在绿色区域里 { //绿色+1 greennum++; } else { //其他颜色 othernum++; } } } Console.WriteLine(greennum + ":绿色"); Console.WriteLine(hsvmat.Rows * hsvmat.Cols + ":总"); Console.WriteLine(yellownum + ":黄色"); Console.WriteLine(bluenum + ":蓝色"); // 灰度 matGray_car = matPlate.CvtColor(ColorConversionCodes.BGR2GRAY); //二值化 Mat matshoid_th = matGray_car.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); matshoid = new Mat(); // 判断 取反 否 if (bluenum < yellownum && yellownum > greennum) { // 取反 matshoid = 255 - matshoid_th; } else if (bluenum > yellownum && bluenum > greennum) { matshoid = matGray_car.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); } else if (greennum > yellownum && greennum > bluenum) { // 取反 matshoid = 255 - matshoid_th; } else { matshoid = matGray_car.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); } // 车牌高度大于20的去除边框和柳钉 Mat clearBorder = new Mat(); Mat clearMoDing = new Mat(); if (matshoid.Height > 22) { // 去除边框 clearBorder = ClearBorder(matshoid); // 去除柳钉 clearMoDing = ClearMaoding(matshoid, 4); } else if (matshoid.Height <= 22 && matshoid.Height > 20) { // 去除边框 clearBorder = ClearBorder(matshoid); // 去除柳钉 clearMoDing = ClearMaoding(matshoid, 3); } else { clearMoDing = matshoid; } // 膨胀 Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(1, 1)); matDilate_car = clearMoDing.MorphologyEx(MorphTypes.Dilate, element); //点的二维数组 OpenCvSharp.Point[][] contours = null; HierarchyIndex[] hierarchyIndexs = null; matDilate_car.FindContours(out contours, out hierarchyIndexs, RetrievalModes.External, ContourApproximationModes.ApproxSimple); matWithFalg_car = matPlate.Clone(); matWithFalg_car.DrawContours(contours, -1, Scalar.Red); matWithRects = matPlate.Clone(); // 创建集合 存储分割后的图片 -- 用于 识别 List <Mat> ListMat = new List <Mat>(); // 切割的矩形 图 List <Rect> ListRect = new List <Rect>(); for (int index = 0; index < contours.Length; index++) { Rect rect = Cv2.BoundingRect(contours[index]); ListRect.Add(rect); matWithRects.Rectangle(rect, Scalar.Red); } // 对分割的字符排序 SortRectsByLeft_ASC(ListRect); foreach (var rect in ListRect) { Mat matchar = matPlate.SubMat(rect); // 切割矩形 Console.WriteLine("========= 宽:" + matchar.Width + " 高:" + matchar.Height); // 判断 太小的不要 if (matchar.Width >= 3 && matchar.Height >= 10) { PlateCategory plateCate = Plate_SVM.Test(matchar); ListMat.Add(matchar); Console.WriteLine(ListMat.Count + " 个"); } Console.WriteLine("========= 宽:" + rect.Width + " 高:" + rect.Height + " X:" + rect.X + " Y:" + rect.Y); } return(ListMat); }