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; } }