文章目录

说明

1、模板匹配不支持放大缩小,图像旋转,不适用于缩放与旋转情况;应保证模板图像与搜寻的图像具有相同的大小,方向;
2、模板匹配用来寻找一幅图像中与模板最匹配的部分,模板图像大小必须小于搜寻的原图像,且类型必须相同;
3、CvInvoke.MatchTemplate()函数:输出比较映射图像result类型为:32位单通道图像,尺寸大小为 : (W-w+1)*(H-h+1);映射图像结果中最佳匹配的地方最亮,图像像素值最大;可先将映射图像归一化到0-1,再寻找maxLoc与maxValue,设定一个阈值,大于阈值的认为是匹配图像结果(实现多模板匹配);匹配方法常用:CcorrNormed(归一化相关匹配法)


4、CvInvoke.MinMaxLoc() : 寻找图像中最大最小像素值及其位置;

Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System.Drawing;

namespace lesson20
{
   
    class Program
    {
   
        static void Main(string[] args)
        {
   
            ///单模板匹配
            //Mat src = CvInvoke.Imread("src.png");
            //CvInvoke.Imshow("src", src);
            //Mat result = src.Clone();

            //Mat tempImg = CvInvoke.Imread("temp.png");
            //int rows_dst = src.Rows - tempImg.Rows + 1;
            //int cols_dst = src.Cols - tempImg.Cols + 1;
            //Mat dst = new Mat(rows_dst,cols_dst,DepthType.Cv32F,1); //创建合适大小的32位浮点型单通道图像
            //CvInvoke.MatchTemplate(src, tempImg, dst, TemplateMatchingType.CcoeffNormed); //模板匹配
            //CvInvoke.Imshow("match", dst); //输出32位匹配图(imshow()自动缩放)
            //CvInvoke.Normalize(dst, dst, 0, 1, NormType.MinMax, dst.Depth);//归一化到0-1

            //double minValue = 1000, maxvalue = -1;
            //Point minLoc = new Point();
            //Point maxLoc = new Point();

            //CvInvoke.MinMaxLoc(dst, ref minValue, ref maxvalue, ref minLoc, ref maxLoc); //寻找最大最小值位置
            //CvInvoke.Rectangle(result, new Rectangle(maxLoc.X, maxLoc.Y, tempImg.Width, tempImg.Height), 
            // new MCvScalar(0, 255, 0), 2);
            //CvInvoke.Imshow("result", result);
            //CvInvoke.WaitKey(0);

            ///视频模板匹配
            //VideoCapture cap = new VideoCapture("1.mp4");
            //Mat tempImg = CvInvoke.Imread("green.jpg");
            //if(!cap.IsOpened)
            //{
   
            // Console.WriteLine("could not open the video...");
            // return;
            //}
            //Mat frame = new Mat();
            //while(true)
            //{
   
            // cap.Read(frame);
            // if(frame.IsEmpty)
            // {
   
            // continue;
            // }
            // int matchresult_rows = frame.Rows - tempImg.Rows + 1;
            // int matchresult_cols = frame.Cols - tempImg.Cols + 1;
            // Mat matchresult_img = new Mat(matchresult_rows, matchresult_cols, DepthType.Cv32F, 1);
            // CvInvoke.MatchTemplate(frame, tempImg, matchresult_img, TemplateMatchingType.CcoeffNormed);
            // CvInvoke.Imshow("match result", matchresult_img);
            // CvInvoke.Normalize(matchresult_img, matchresult_img, 0, 1, 
            // NormType.MinMax, matchresult_img.Depth); //归一化
            // double minValue = 0, maxValue = 0;
            // Point minLoc = new Point(0, 0);
            // Point maxLoc = new Point(0, 0);

            // CvInvoke.MinMaxLoc(matchresult_img, ref minValue, ref maxValue, ref minLoc, ref maxLoc);
            // CvInvoke.Rectangle(frame, new Rectangle(maxLoc.X, maxLoc.Y, tempImg.Width, tempImg.Height), new MCvScalar(0, 255, 0), 2);

            // CvInvoke.Imshow("template trace", frame);
            // if(CvInvoke.WaitKey(30) == 27)
            // {
   
            // break;
            // }
            //}

            ///多模板匹配方法
            Mat src = CvInvoke.Imread("src.png");
            CvInvoke.Imshow("src", src);
            Mat result = src.Clone();

            Mat tempImg = CvInvoke.Imread("temp.png");
            int matchImg_rows = src.Rows - tempImg.Rows + 1;
            int matchImg_cols = src.Cols - tempImg.Cols + 1;
            Mat matchImg = new Mat(matchImg_rows, matchImg_rows, DepthType.Cv32F,1); //存储匹配结果
            CvInvoke.MatchTemplate(src, tempImg, matchImg, TemplateMatchingType.CcoeffNormed);
            CvInvoke.Imshow("match", matchImg);
            CvInvoke.Normalize(matchImg, matchImg, 0, 1, NormType.MinMax, matchImg.Depth); //归一化
            double minValue = 0.0, maxValue = 0.0;
            Point minLoc = new Point();
            Point maxLoc = new Point();
            CvInvoke.MinMaxLoc(matchImg,ref minValue,ref maxValue,ref minLoc,ref maxLoc);

            Image<Gray, Single> imgMatch = matchImg.ToImage<Gray, Single>();

            int count = 0;
            int tempH = 0, tempW = 0;
            for(int i =0; i < imgMatch.Rows;i++)
            {
   
                for(int j = 0; j < imgMatch.Cols;j++)
                {
   
                    float matchValue = imgMatch.Data[i,j,0];
                    if((matchValue > 0.7) && (Math.Abs(j - tempW) > 10) && (Math.Abs(i - tempH)> 10))  //只绘制处于最大范围内的点
                    {
   
                        count++;
                        CvInvoke.Rectangle(result, new Rectangle(j, i, tempImg.Width, tempImg.Height), new MCvScalar(255, 0, 0), 2);
                        tempH = i;
                        tempW = j;
                    }
                }
            }
            CvInvoke.Imshow("result", result);
            CvInvoke.WaitKey(0);
        }
    }
}

效果

1、单模板匹配:(只寻找最佳匹配的一幅图像)

2、视频模板匹配:

3、多模板匹配: