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 WindowsFormsApp1; using System.Diagnostics; using System.Threading; public class ProcessImg { // 对单个图像进行模板匹配 public static (double score, Rect? coords) MatchTemplate(string imgPath, string templatePath) { // 确保图像和模板文件存在 // 读取图像和模板 var img = Cv2.ImRead(imgPath, ImreadModes.Color); 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.4; // 可以根据需要调整阈值 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 Rect ProcessImagesInFolder(string folderPath, string actPath, string outputFolderPath, string resImgPath) { // 获取所有图像文件 var imageFiles = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly) .Where(file => file.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) || file.EndsWith(".png", StringComparison.OrdinalIgnoreCase) || file.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase)) .ToList(); // 确保输出文件夹存在 Directory.CreateDirectory(outputFolderPath); // 计算线程数量(文件数量的一半) int numThreads = Math.Max(1, imageFiles.Count); // 用于存储每个图像的得分和坐标 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(actPath, picPath); if (score > 0.4) { 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(); Rect rect = best.coords.Value; if (best.imagePath != null && best.coords.HasValue) { // 结果图像的路径 string fileName = Path.GetFileNameWithoutExtension(best.imagePath) + "_result.jpg"; string outputPath = Path.Combine(outputFolderPath, fileName); // 在最佳图像上绘制矩形并保存结果 DrawRectangleOnImage(resImgPath, rect, outputPath); } return rect; } // 在图像上绘制矩形并保存结果 public static void DrawRectangleOnImage(string imagePath, Rect rect, string outputPath) { using (var mat = Cv2.ImRead(imagePath, ImreadModes.Color)) { // 将 Mat 转换为 Bitmap using (var bitmap = BitmapConverter.ToBitmap(mat)) { // 创建一个 Bitmap 的副本,以便在其上绘制 using (var bitmapCopy = new Bitmap(bitmap)) using (var graphics = Graphics.FromImage(bitmapCopy)) { // 创建一个红色边框,宽度为 2 像素 var pen = new Pen(Color.Red, 2); // 绘制矩形 graphics.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); // 保存结果图像 bitmapCopy.Save(outputPath, ImageFormat.Jpeg); } } } } }