AoiTemplateMethod.cs 3.6 KB
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
using OpenCvSharp.Blob;
using OpenCvSharp.XFeatures2D;

namespace AOI
{
    /// <summary>
    /// 模板匹配
    /// </summary>
    public class AoiTemplateMethod : AoiMethod
    {
        /// <summary>
        /// 相似度百分比
        /// </summary>
        public double SamePercent = 50;

        public override ResultBean Check(Image standardImage, Image imageToCheck)
        {
            ResultBean resultBean = new ResultBean(MethodName,4,SamePercent,SamePercent);
           
            bool needCut = true;
            Image standardRoiImg = GetRoiImage(standardImage, needCut);
            resultBean.standardRoiImage = standardRoiImg;
            double percent = GetTemplateMatchPercent(standardImage, imageToCheck, out Image cutImg);
            bool result = false;
            if(SamePercent > 100)
            {
                SamePercent = 100;
            }

            if(percent >= SamePercent)
            {
                result = true;
            }
            resultBean.currentRoiImage = cutImg;
            resultBean.result = result;
            resultBean.percentValue =Math.Round( percent,3);
            return resultBean;
        }

        /// <summary>
        /// 获取模板相似度
        /// </summary>
        /// <param name="standardImage"></param>
        /// <param name="imageToCheck"></param>
        /// <param name="cutImg"></param>
        /// <returns></returns>
        public double GetTemplateMatchPercent(Image standardImage, Image imageToCheck, out Image cutImg)
        {
            bool needCut = true;
            //标准图中的Mart区域
            Image templateImage = GetRoiImage(standardImage, RoiPath, needCut);
            //搜索区域
            Image searchImage = GetRoiImage(imageToCheck, RoiPath, needCut);
            cutImg = searchImage;
            try
            {
                //searchImage = imageToCheck;
                if (templateImage != null && searchImage != null)
                {
                    Mat searchMat = ImageUtil.ToMat(new Bitmap(searchImage));
                    Mat templateMat = ImageUtil.ToMat(new Bitmap(templateImage));

                    Mat result = new Mat(searchMat.Cols - templateMat.Cols + 1, searchMat.Rows - templateMat.Rows + 1, MatType.CV_32FC1);

                    //进行匹配(1母图,2模版子图,3返回的result,4匹配模式_这里的算法比opencv少,具体可以看opencv的相关资料说明)
                    Cv2.MatchTemplate(searchMat, templateMat, result, TemplateMatchModes.CCoeffNormed);

                    //对结果进行归一化(这里我测试的时候没有发现有什么用,但在opencv的书里有这个操作,应该有什么神秘加成,这里也加上)
                    //Cv2.Normalize(result, result, 1, 0, NormTypes.MinMax, -1);
                    /// 通过函数 minMaxLoc 定位最匹配的位置
                    /// (这个方法在opencv里有5个参数,这里我写的时候发现在有3个重载,看了下可以直接写成拿到起始坐标就不取最大值和最小值了)
                    /// minLocation和maxLocation根据匹配调用的模式取不同的点
                    Cv2.MinMaxLoc(result, out double minVal, out double maxVal, out OpenCvSharp.Point minLocation, out OpenCvSharp.Point maxLocation);
                    return maxVal * 100;
                }
            }catch(Exception ex)
            {
                Console.Write(ex.ToString());
            }
            return 0;
        }
    }
}