1:建好测试Demo
- C#项目中添加好OpenCVSharp安装包 如下图(图中是VS2015版本)
- NuGet工具给项目添加OpenCvSharp3-AnyCPU:
- 工具>>NuGet包管理器>>管理解决方案的NuGet程序包
2:测试Demo
- 首先,添加引用:
using OpenCvSharp
; - 其次,添加如下函数代码代码段
对模板匹配方法使用前的准备
-
/// <summary> /// 模板匹配 /// </summary> /// <param name="srcImg">被匹配图像路径</param> /// <param name="tempImg">模板图像路径</param> /// <returns>当前匹配完成后 模板在匹配图像中左上角的坐标点</returns> public OpenCvSharp.Point TemplateMatch(string srcImg, string tempImg, out double matchVal) { OpenCvSharp.Point tempPoint = new OpenCvSharp.Point(); Mat srcImage = Cv2.ImRead(srcImg, ImreadModes.Grayscale); Mat tempImage = Cv2.ImRead(tempImg, ImreadModes.Grayscale); Bitmap bmp = MatchTemplate(tempImage, srcImage, out tempPoint, out matchVal); //保存图像路径 bmp.Save(System.AppDomain.CurrentDomain.BaseDirectory + @"ImgFile\processedImg" + DateTime.Now.ToString("yyMMddHHmmss") + ".bmp"); return tempPoint; }
模板匹配方法
-
/// <summary> /// 模板匹配 /// </summary> /// <param name="tempalte">模板图片像</param> /// <param name="srcPic">被匹配图像</param> /// <param name="tempPoint">返回模板图像在匹配图像中的坐标位置</param> /// <returns>标注匹配区域的图像</returns> private Bitmap MatchTemplate(Mat tempalte, Mat srcPic, out OpenCvSharp.Point tempPoint, out double matchValue) { Mat result = new Mat(); //模板匹配 Cv2.MatchTemplate(srcPic, tempalte, result, TemplateMatchModes.CCoeffNormed);//CCoeffNormed 最好匹配为1,值越小匹配越差 Double minVul; Double maxVul; OpenCvSharp.Point minLoc = new OpenCvSharp.Point(0, 0); OpenCvSharp.Point maxLoc = new OpenCvSharp.Point(0, 0); OpenCvSharp.Point matchLoc = new OpenCvSharp.Point(0, 0); //归一化 Cv2.Normalize(result, result, 0, 1, NormTypes.MinMax, -1); //寻找极值 Cv2.MinMaxLoc(result, out minVul, out maxVul, out minLoc, out maxLoc); //最大值坐标 matchLoc = maxLoc; Mat mask = srcPic.Clone();//复制整个矩阵 //画框显示 :对角线画框,起点和终点,都用Point,线宽 Cv2.Rectangle(mask, matchLoc, new OpenCvSharp.Point(matchLoc.X + tempalte.Cols, matchLoc.Y + tempalte.Rows), Scalar.Green, 2);//2代表画的线条的宽细程度 //Console.WriteLine("最大值:{0},X:{1},Y:{2}", maxVul, matchLoc.Y, matchLoc.X); matchValue = maxVul; tempPoint.X = matchLoc.X; tempPoint.Y = matchLoc.Y; //循环查找画框显示 Double threshold = 0.91; Mat maskMulti = srcPic.Clone(); for (int i = 1; i < result.Rows - tempalte.Rows; i += tempalte.Rows) { for (int j = 1; j < result.Cols - tempalte.Cols; j += tempalte.Cols) { Rect roi = new Rect(j, i, tempalte.Cols, tempalte.Rows); //建立感兴趣 Mat RoiResult = new Mat(result, roi); Cv2.MinMaxLoc(RoiResult, out minVul, out maxVul, out minLoc, out maxLoc);//查找极值 matchLoc = maxLoc;//最大值坐标 if (maxVul > threshold) { //画框显示 Cv2.Rectangle(maskMulti, new OpenCvSharp.Point(j + maxLoc.X, i + maxLoc.Y), new OpenCvSharp.Point(j + maxLoc.X + tempalte.Cols, i + maxLoc.Y + tempalte.Rows), Scalar.Green, 2); string axis = '(' + Convert.ToString(i + maxLoc.Y) + ',' + Convert.ToString(j + maxLoc.X) + ')'; Cv2.PutText(maskMulti, axis, new OpenCvSharp.Point(j + maxLoc.X, i + maxLoc.Y), HersheyFonts.HersheyPlain, 1, Scalar.Red, 1, LineTypes.Link4); } } } //返回匹配后图像 return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mask); }
3:测试结果
- 被匹配图像
- 模板图像
- 匹配结果
- 效果可以滴,但是经过多次不同程度实验结果表明,误差还是有的
3:学习资料
- OpenCv中文网站:OpenCV中文网站-论坛 - Powered by Discuz!
- OpenCV官方教程 -Template Matching:OpenCV模板匹配_w3cschool