using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using CvPoint = OpenCvSharp.Point; using CvSize = OpenCvSharp.Size; namespace OpenCvSharpTest { public static class InstructionManualTest { public static void InstructionManualTest1() { //读取图片 Bitmap Bitmapimage = new Bitmap("D:\\work\\WindowsFormsTest\\OpenCvSharpTest\\20251108153639.jpg"); //Mat image = Cv2.ImRead("D:\\work\\WindowsFormsTest\\OpenCvSharpTest\\20251108153840.jpg"); Mat image = BitmapToMat(Bitmapimage); Mat gray = new Mat(); //灰度化预处理 Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY); //Cv2.ImShow("gray", gray); //二值化 Mat binary = new Mat(); Cv2.Threshold(gray, binary, 90, 255, ThresholdTypes.Binary); //Cv2.ImShow("binary", ReadCodeTest.ResizeMat(binary)); //闭运算 Mat kernelX = new Mat(); kernelX = Cv2.GetStructuringElement(MorphShapes.Rect, new CvSize(15, 15)); Mat Open = new Mat(); Cv2.MorphologyEx(binary, Open, MorphTypes.Open, kernelX); Cv2.ImShow("Opendimg", ReadCodeTest.ResizeMat(Open)); // 查找轮廓 CvPoint[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours(Open, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 筛选轮廓(根据面积) List filteredBlobs = new List(); int minPixelCount = 2000000; int maxPixelCount = 6000000; double minRectangularity = 0.8; // 最小矩形度 foreach (CvPoint[] contour in contours) { double area = Cv2.ContourArea(contour); if (area >= minPixelCount && area <= maxPixelCount) {// 计算矩形度 double rectangularity = CalculateRectangularity(contour); // 矩形度筛选 if (rectangularity >= minRectangularity) { // 获取轮廓的边界矩形 Rect boundingRect = Cv2.BoundingRect(contour); BlobInfo blobInfo = new BlobInfo { Contour = contour, Area = area, Rectangularity = rectangularity, BoundingRect = boundingRect, Center = new CvPoint(boundingRect.X + boundingRect.Width / 2, boundingRect.Y + boundingRect.Height / 2) }; filteredBlobs.Add(blobInfo); Console.WriteLine($"轮廓 - 面积: {area:F0} 像素, 矩形度: {rectangularity:F2}"); } } } Console.WriteLine($"原始轮廓数量: {contours.Length}"); Console.WriteLine($"筛选后轮廓数量: {filteredBlobs.Count}"); if (filteredBlobs.Count == 1) { Console.WriteLine("有说明书,输出状态为正常"); } else { Console.WriteLine("没有说明书或是识别出多个说明书,输出状态为异常"); } // 在原图上绘制筛选后的轮廓 Mat outputImage = new Mat(); foreach (var blobInfo in filteredBlobs) { Cv2.DrawContours(image, new[] { blobInfo.Contour }, -1, Scalar.Green, 100); } Cv2.ImShow("Output Image", ReadCodeTest.ResizeMat(image)); // 显示统计信息 if (filteredBlobs.Count > 0) { double avgRectangularity = filteredBlobs.Average(b => b.Rectangularity); double maxRectangularity = filteredBlobs.Max(b => b.Rectangularity); double minRectangularityFound = filteredBlobs.Min(b => b.Rectangularity); Console.WriteLine($"\n统计信息:"); Console.WriteLine($"平均矩形度: {avgRectangularity:F2}"); Console.WriteLine($"最大矩形度: {maxRectangularity:F2}"); Console.WriteLine($"最小矩形度: {minRectangularityFound:F2}"); } Cv2.WaitKey(0); } /// /// 计算轮廓的矩形度 /// 矩形度 = 轮廓面积 / 最小外接矩形面积 /// /// 轮廓点集 /// 矩形度值 (0-1) static double CalculateRectangularity(CvPoint[] contour) { // 计算轮廓面积 double contourArea = Cv2.ContourArea(contour); // 获取最小外接矩形 RotatedRect minAreaRect = Cv2.MinAreaRect(contour); // 计算最小外接矩形面积 double rectArea = minAreaRect.Size.Width * minAreaRect.Size.Height; // 避免除零错误 if (rectArea <= 0) return 0; // 计算矩形度 double rectangularity = contourArea / rectArea; // 确保值在合理范围内 return Math.Max(0, Math.Min(1, rectangularity)); } /// /// 将Bitmap转换为Mat /// /// 源Bitmap /// 对应的Mat对象 static Mat BitmapToMat(Bitmap bitmap) { using (var ms = new MemoryStream()) { bitmap.Save(ms, ImageFormat.Bmp); ms.Position = 0; return Mat.FromStream(ms, ImreadModes.Color); } } } /// /// Blob信息类 /// class BlobInfo { /// /// 轮廓点集 /// public CvPoint[] Contour { get; set; } /// /// 轮廓面积(像素数量) /// public double Area { get; set; } /// /// 矩形度 (0-1) /// public double Rectangularity { get; set; } /// /// 边界矩形 /// public Rect BoundingRect { get; set; } /// /// 中心点 /// public CvPoint Center { get; set; } } }