示例#1
0
 //预测图片类型是否正确
 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;
     }
 }
示例#2
0
        //测试
        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;
            }
        }
示例#3
0
        // 字符保存
        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);
        }
示例#4
0
        // 保存图片样本
        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);
        }
示例#5
0
 public PlateImage(string fileName, string name, PlateCategory plateCategory, OpenCvSharp.Size
                   matSize)
 {
     this.FileName      = fileName;
     this.Name          = name;
     this.PlateCategory = plateCategory;
     this.MatSize       = matSize;
 }
示例#6
0
        //保存图片样本
        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);
        }
示例#7
0
 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;
 }
示例#8
0
        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);
        }
示例#9
0
        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));
        }
示例#10
0
        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);
        }
示例#11
0
        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);
            }
        }
示例#12
0
        /// <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");
        }
示例#13
0
        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);
        }
示例#14
0
        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);
        }
示例#15
0
        //颜色法
        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);
        }
示例#16
0
        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);
        }