AoiEyemTemplateMethod.cs 5.2 KB
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
using OpenCvSharp.Blob;
using OpenCvSharp.XFeatures2D;
using static AOI.Eyemlib;

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

        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, angle;
            (percent,angle) = GetTemplateMatchPercent(standardImage, imageToCheck, out Image cutImg);
            bool result = false;
            if(SamePercent > 100)
            {
                SamePercent = 100;
            }

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

        /// <summary>
        /// 获取模板相似度
        /// </summary>
        /// <param name="standardImage"></param>
        /// <param name="imageToCheck"></param>
        /// <param name="cutImg"></param>
        /// <returns></returns>
        public (double,double) GetTemplateMatchPercent(Image standardImage, Image imageToCheck, out Image cutImg)
        {
            var template = Eyemlib.eyemCvtToEyemImage((Bitmap)standardImage);
            var search = Eyemlib.eyemCvtToEyemImage((Bitmap)imageToCheck);

            int iNumMatches = 15;//目标个数
            double dToleranceAngle = 0.0;//要检测目标容忍角度
            double dMaxOverlap = 0.0;//重叠比例
            double dScore = 0.8;//最小分数
            cutImg = null;
            //模板匹配
            EyemTargetMatch[] tpResults = new EyemTargetMatch[iNumMatches];
            IntPtr ResultHandle = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(EyemTargetMatch)) * tpResults.Length);
            if (RoiPath==null)
                return (0d, 0d);
            var rect = RoiPath.GetBounds();
            if (rect== RectangleF.Empty)
                return (0d, 0d);
            rect.X -= CenterOffsetX;
            rect.Y -= CenterOffsetY;
            //框选模板匹配位置(通常左上角位置选一块)
            EyemRect tpRoiTemplate = new EyemRect();
            tpRoiTemplate.iXs = (int)(rect.X);
            tpRoiTemplate.iYs = (int)(rect.Y);
            tpRoiTemplate.iWidth = (int)rect.Width;
            tpRoiTemplate.iHeight = (int)rect.Height;
            //var search = eyemCvtToEyemImage((Bitmap)imageToCheck);
            Eyemlib.eyemCopyRegion(search, tpRoiTemplate, out Eyemlib.EyemImage templ);
            if(templ.iWidth==0)
                return (0, 0);
            cutImg = eyemCvtToBitmap(templ);
            //可以用来调试查看图像
            //Eyemlib.eyemNamedWindow("templ");
            //Eyemlib.eyemImshow("templ", templ);
            //Eyemlib.eyemWaitkey();
            //Eyemlib.eyemImshow("templ", template);
            //Eyemlib.eyemWaitkey();
            Eyemlib.eyemMakeNCCModel(templ, 256);
            //额外用法包括确定电容正负极,比如模板为0方向,搜寻到目标角度|angle|>45°判断极性错误等等
            var flag = Eyemlib.eyemFindNCCModel(template, dToleranceAngle, iNumMatches, dMaxOverlap, dScore, true, ResultHandle, out EyemImage tpDstImg);
            if (flag != 0)
                return (0,0);

            eyemImageFree(ref templ);
            eyemImageFree(ref template);
            eyemImageFree(ref search);

            tpResults = Eyemlib.eyemIntPtr2StructArray<EyemTargetMatch>(ResultHandle, tpResults.Length).ToArray();

            int matchscore = 0;
            double anglescore = 0;
            //检测到目标
            for (int i = 0; i < tpResults.Length; i++)
            {
                if (tpResults[i].fMatchScore > 0 && rect.Contains(tpResults[i].fCenterX, tpResults[i].fCenterY))
                {
                    matchscore = (int)(tpResults[i].fMatchScore*100);
                    anglescore = Math.Abs(tpResults[i].fMatchAngle);

                    Console.WriteLine(string.Format("目标{0},位置({1},{2}),匹配分数{3}",
                            i, tpResults[i].fCenterX.ToString("F3"), tpResults[i].fCenterY.ToString("F3"), tpResults[i].fMatchScore.ToString("F3")));


                }
            }
            if (matchscore == 0) {
                Bitmap bitmap = Eyemlib.eyemCvtToBitmap(tpDstImg);
                bitmap.Save("\\match.png");
            }
            eyemImageFree(ref tpDstImg);
            Marshal.FreeHGlobal(ResultHandle);
            return (matchscore,anglescore);
        }
    }
}