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; namespace OpenCvSharpTest { public static class ReadCodeTest { public static string Read10CodeTest1(Bitmap Bitmapimage) { bool IsShuZhi = false; //读取图片 //Mat image = Cv2.ImRead("D:\\work\\WindowsFormsTest\\TestImage\\20250609165353.jpg"); Mat image = BitmapToMat(Bitmapimage); Mat gray = new Mat(); //灰度化预处理 Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY); Cv2.ImShow("gray", ResizeMat(gray)); //二值化 Mat binary = new Mat(); Cv2.Threshold(gray, binary, 100, 255, ThresholdTypes.Binary); //Cv2.ImShow("binary", ResizeMat(binary)); //计算梯度 Mat gradX = new Mat(); if (IsShuZhi) { Cv2.Sobel(binary, gradX, MatType.CV_32F, 1, 0, 1, 1, 0, BorderTypes.Default); } else { Cv2.Sobel(binary, gradX, MatType.CV_32F, 0, 1, 1, 1, 0, BorderTypes.Default); } //Cv2.ImShow("gradX", ResizeMat(gradX)); //计算绝对值 Mat absGradX = new Mat(); Cv2.ConvertScaleAbs(gradX, absGradX, 1, 0); //Cv2.ImShow("absGradX", ResizeMat(absGradX)); //闭运算 Mat kernelX = new Mat(); if (IsShuZhi) { kernelX = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(80, 5)); } else { kernelX = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(5, 40)); } Mat closed = new Mat(); Cv2.MorphologyEx(absGradX, closed, MorphTypes.Close, kernelX); Cv2.ImShow("closedimg", ResizeMat(closed)); //查找轮廓 OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours(closed, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple); List filteredBlobs = new List(); int minPixelCount = 1000; int maxPixelCount = 6000000; double minRectangularity = 0.6; // 最小矩形度 foreach (OpenCvSharp.Point[] 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 OpenCvSharp.Point(boundingRect.X + boundingRect.Width / 2, boundingRect.Y + boundingRect.Height / 2) }; filteredBlobs.Add(blobInfo); Console.WriteLine($"轮廓 - 面积: {area:F0} 像素, 矩形度: {rectangularity:F2}"); } } } // 在原图上绘制筛选后的轮廓 //Mat outputImage = new Mat(); //foreach (var blobInfo in filteredBlobs) //{ // Cv2.DrawContours(image, new[] { blobInfo.Contour }, -1, Scalar.Green, 5); //} //Cv2.ImShow("Output Image", ReadCodeTest.ResizeMat(image)); //if (contours.Count() == 0) // return ""; ////筛选矩形并找到最大面积 //var maxContour = contours.OrderByDescending(c => Cv2.ContourArea(c)).First(); if (filteredBlobs.Count() == 0) { Cv2.WaitKey(0); return ""; } OpenCvSharp.Rect ShowboundingRect = Cv2.BoundingRect(filteredBlobs.First().Contour); //Cv2.Rectangle(image, boundingRect, Scalar.Red, 2); OpenCvSharp.Rect roi = new OpenCvSharp.Rect(ShowboundingRect.X + (ShowboundingRect.Width / 4), ShowboundingRect.Y - 25, ShowboundingRect.Width / 2, ShowboundingRect.Height + 50); Mat roiMat = binary.SubMat(roi).Clone(); Cv2.ImShow("roi", ResizeMat(roiMat)); Mat binary2 = new Mat(); // 使用THRESH_BINARY_INV反转黑白,黑色物体变为白色区域 Cv2.Threshold(roiMat, binary2, 128, 255, ThresholdTypes.BinaryInv); OpenCvSharp.Point[][] contours1; HierarchyIndex[] hierarchy1; Cv2.FindContours(binary2, out contours1, out hierarchy1, RetrievalModes.External, ContourApproximationModes.ApproxSimple); Console.WriteLine(contours1.Count().ToString()); var widths = contours1.OrderBy(c => Cv2.BoundingRect(c).Y).Select(c => Cv2.BoundingRect(c).Height).ToArray(); double ave = widths.Average(); var CodeResult = widths.Select(w => w > ave ? 1 : 0).ToArray(); Console.WriteLine(string.Join("", CodeResult)); //// 显示结果 //Cv2.ImShow("Result", ResizeMat(image)); Cv2.WaitKey(0); ////显示结果 //Cv2.DestroyAllWindows(); image.Dispose(); return string.Join("", CodeResult); //return ""; } public static void FindOcrCode() { Mat image1 = Cv2.ImRead("D:\\work\\WindowsFormsTest\\TestImage\\wechat_2025-09-03_112903_716.png"); Mat image2 = Cv2.ImRead("D:\\work\\WindowsFormsTest\\TestImage\\wechat_2025-09-03_112903_716_1.png"); // 查找轮廓 OpenCvSharp.Point[][] contours1; OpenCvSharp.Point[][] contours2; Cv2.FindContours(image1, out contours1, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple); Cv2.FindContours(image2, out contours2, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 轮廓匹配 double similarity = Cv2.MatchShapes(contours1[0], contours2[0], ShapeMatchModes.I1); // 相似度值越小表示轮廓越相似 if (similarity < 0.1) { Console.WriteLine("轮廓非常相似"); } } public static Mat ResizeMat(Mat mat) { Mat resizedImage = new Mat(); double maxSize = 800; double scale = Math.Min(maxSize / mat.Width, maxSize / mat.Height); OpenCvSharp.Size scaledSize = new OpenCvSharp.Size(mat.Width * scale, mat.Height * scale); Cv2.Resize(mat, resizedImage, scaledSize); return resizedImage; } /// /// 将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); } } /// /// 计算轮廓的矩形度 /// 矩形度 = 轮廓面积 / 最小外接矩形面积 /// /// 轮廓点集 /// 矩形度值 (0-1) static double CalculateRectangularity(OpenCvSharp.Point[] 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)); } } }