151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 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;
 | |
| //cyf
 | |
| 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;
 | |
|     }
 | |
| 
 | |
| 
 | |
| }
 |