10.20PLC+相机2.3视觉修改
This commit is contained in:
		
							
								
								
									
										150
									
								
								Check.Main/Process_Img.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								Check.Main/Process_Img.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| using OpenCvSharp; | ||||
| using System; | ||||
| using System.Drawing; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Drawing.Imaging; | ||||
| using OpenCvSharp.Extensions; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Threading.Tasks; | ||||
| using System.Diagnostics; | ||||
| using System.Threading; | ||||
|  | ||||
| public class ProcessImg | ||||
| { | ||||
|     // 对单个图像进行模板匹配 | ||||
|     | ||||
|     public static (double score, Rect? coords) MatchTemplate(Mat img, string templatePath) | ||||
|     { | ||||
|         // 确保图像和模板文件存在 | ||||
|  | ||||
|  | ||||
|         // 读取图像和模板 | ||||
|          | ||||
|         var template = Cv2.ImRead(templatePath, ImreadModes.Color); | ||||
|  | ||||
|         // 创建一个模板匹配的结果矩阵 | ||||
|         var result = new Mat(); | ||||
|         Cv2.MatchTemplate(img, template, result, TemplateMatchModes.CCoeffNormed); | ||||
|  | ||||
|         // 查找最大匹配值 | ||||
|         Cv2.MinMaxLoc(result, out _, out var maxVal, out _, out var maxLoc); | ||||
|  | ||||
|         // 如果找到的最大匹配值大于阈值 | ||||
|         double threshold = 0.3; // 可以根据需要调整阈值 | ||||
|         if (maxVal >= threshold) | ||||
|         { | ||||
|             // 计算匹配的坐标      | ||||
|             var topLeft = maxLoc; | ||||
|             var rect = new Rect(topLeft.X, topLeft.Y, template.Width, template.Height); | ||||
|  | ||||
|             return (maxVal, rect); | ||||
|         } | ||||
|  | ||||
|         return (0, null); | ||||
|     }    | ||||
|  | ||||
|     // 遍历文件夹中的所有图像文件进行模板匹配,并找到最佳得分图像 | ||||
|     public static Double ProcessImagesInFolder(string folderPath, Mat img) | ||||
|     { | ||||
|         // 获取所有图像文件 | ||||
|         var imageFiles = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly) | ||||
|             .Where(file => file.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) || | ||||
|                            file.EndsWith(".png", StringComparison.OrdinalIgnoreCase) || | ||||
|                            file.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase)) | ||||
|             .ToList(); | ||||
|  | ||||
|        | ||||
|  | ||||
|         // 确保输出文件夹存在 | ||||
|          | ||||
|  | ||||
|         // 线程数量 | ||||
|         int numThreads = 5; | ||||
|  | ||||
|         // 用于存储每个图像的得分和坐标 | ||||
|         var bestMatch = new ConcurrentBag<(string imagePath, double score, Rect? coords)>(); | ||||
|         DateTime startTime = DateTime.Now; | ||||
|         Stopwatch sw = new Stopwatch(); | ||||
|         sw.Start(); | ||||
|  | ||||
|         Parallel.ForEach(imageFiles, new ParallelOptions { MaxDegreeOfParallelism = numThreads }, picPath => | ||||
|         { | ||||
|             DateTime threadStartTime = DateTime.Now; | ||||
|  | ||||
|             var (score, coords) = MatchTemplate(img, picPath); | ||||
|  | ||||
|              | ||||
|              | ||||
|                 bestMatch.Add((picPath, score, coords)); | ||||
|              | ||||
|  | ||||
|             DateTime threadEndTime = DateTime.Now; | ||||
|             TimeSpan threadElapsed = threadEndTime - threadStartTime; | ||||
|             Console.WriteLine($"线程处理 {picPath} 耗时: {threadElapsed.TotalMilliseconds}ms"); | ||||
|         }); | ||||
|  | ||||
|         sw.Stop(); | ||||
|         TimeSpan totalElapsed = sw.Elapsed; | ||||
|         Console.WriteLine($"处理完成,耗时: {totalElapsed.TotalSeconds}秒"); | ||||
|         // 查找最佳得分 | ||||
|         var best = bestMatch.OrderByDescending(m => m.score).FirstOrDefault(); | ||||
|         return best.score; | ||||
|         //if (best.coords.HasValue) | ||||
|         //{ | ||||
|         //    Rect rect = best.coords.Value; | ||||
|         //    return rect; | ||||
|         //} | ||||
|  | ||||
|         //else | ||||
|         //{ | ||||
|         //    return new Rect(0, 0, 0, 0); | ||||
|         //} | ||||
|         | ||||
|  | ||||
|     } | ||||
|     public static Mat BitmapToMat(Bitmap bitmap) | ||||
|     { | ||||
|         if (bitmap == null) | ||||
|         { | ||||
|             throw new ArgumentException("Bitmap is null"); | ||||
|         } | ||||
|  | ||||
|         // 根据 Bitmap 的宽度、高度和像素格式创建一个与其相对应的 Mat | ||||
|         Mat mat = new Mat(bitmap.Height, bitmap.Width, MatType.CV_8UC3); // 假设 Bitmap 是 24-bit RGB | ||||
|  | ||||
|         // 锁定 Bitmap 的内存区域以直接访问它的内存 | ||||
|         BitmapData bitmapData = bitmap.LockBits( | ||||
|             new Rectangle(0, 0, bitmap.Width, bitmap.Height), | ||||
|             ImageLockMode.ReadOnly, | ||||
|             bitmap.PixelFormat | ||||
|         ); | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             // 使用直接内存拷贝将 Bitmap 的数据拷贝到 Mat | ||||
|             unsafe | ||||
|             { | ||||
|                 byte* srcData = (byte*)bitmapData.Scan0; | ||||
|                 byte* dstData = (byte*)mat.DataPointer; | ||||
|  | ||||
|                 int stride = bitmapData.Stride; | ||||
|                 int width = bitmap.Width * 3; // 24bpp 3个字节一个像素 | ||||
|                 int height = bitmap.Height; | ||||
|  | ||||
|                 for (int y = 0; y < height; y++) | ||||
|                 { | ||||
|                     Buffer.MemoryCopy(srcData + y * stride, dstData + y * mat.Step(), width, width); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             bitmap.UnlockBits(bitmapData); | ||||
|         } | ||||
|  | ||||
|         return mat; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user