LuJiaYi/Process_Img.cs

134 lines
4.7 KiB
C#
Raw Normal View History

2024-08-17 18:00:59 +08:00
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);
}
}
}
}
}