| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- 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<BlobInfo> filteredBlobs = new List<BlobInfo>();
- 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;
- }
- /// <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>
- /// 计算轮廓的矩形度
- /// 矩形度 = 轮廓面积 / 最小外接矩形面积
- /// </summary>
- /// <param name="contour">轮廓点集</param>
- /// <returns>矩形度值 (0-1)</returns>
- 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));
- }
- }
- }
|