| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- 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<BlobInfo> filteredBlobs = new List<BlobInfo>();
- 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);
- }
- /// <summary>
- /// 计算轮廓的矩形度
- /// 矩形度 = 轮廓面积 / 最小外接矩形面积
- /// </summary>
- /// <param name="contour">轮廓点集</param>
- /// <returns>矩形度值 (0-1)</returns>
- 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));
- }
- /// <summary>
- /// 将Bitmap转换为Mat
- /// </summary>
- /// <param name="bitmap">源Bitmap</param>
- /// <returns>对应的Mat对象</returns>
- static Mat BitmapToMat(Bitmap bitmap)
- {
- using (var ms = new MemoryStream())
- {
- bitmap.Save(ms, ImageFormat.Bmp);
- ms.Position = 0;
- return Mat.FromStream(ms, ImreadModes.Color);
- }
- }
- }
- /// <summary>
- /// Blob信息类
- /// </summary>
- class BlobInfo
- {
- /// <summary>
- /// 轮廓点集
- /// </summary>
- public CvPoint[] Contour { get; set; }
- /// <summary>
- /// 轮廓面积(像素数量)
- /// </summary>
- public double Area { get; set; }
- /// <summary>
- /// 矩形度 (0-1)
- /// </summary>
- public double Rectangularity { get; set; }
- /// <summary>
- /// 边界矩形
- /// </summary>
- public Rect BoundingRect { get; set; }
- /// <summary>
- /// 中心点
- /// </summary>
- public CvPoint Center { get; set; }
- }
- }
|