【 OpenCV 】基于OpenCV的多角度(带旋转角度)模板匹配算法 C#&OpenCVSharp4

1/模板匹配方法

        /// <summary>
        /// 多角度模板匹配方法
        /// </summary>
        /// <param name="srcImage">待匹配图像</param>
        /// <param name="modelImage">模板图像</param>
        /// <param name="angleStart">起始角度</param>
        /// <param name="angleRange">角度范围</param>
        /// <param name="angleStep">角度步长</param>
        /// <param name="numLevels">金字塔层级</param>
        /// <param name="thresScore">得分阈值</param>
        /// <returns></returns>
        private ResultPoint CircleMatchNcc(Mat srcImage, Mat modelImage, double angleStart, double angleRange, double angleStep, int numLevels, double thresScore,int nccMethod)
        {
            double step = angleRange / ((angleRange / angleStep) / 100);
            double start = angleStart;
            double range = angleRange;

            //定义图片匹配所需要的参数
            int resultCols = srcImage.Cols - modelImage.Cols + 1;
            int resultRows = srcImage.Rows - modelImage.Cols + 1;
            Mat result = new Mat(resultCols, resultRows, MatType.CV_8U);
            Mat src = new Mat();
            Mat model = new Mat();
            srcImage.CopyTo(src);
            modelImage.CopyTo(model);

            //对模板图像和待检测图像分别进行图像金字塔下采样
            for (int i = 0; i < numLevels; i++)
            {
                Cv2.PyrDown(src, src, new Size(src.Cols / 2, src.Rows / 2));
                Cv2.PyrDown(model, model, new Size(model.Cols / 2, model.Rows / 2));
            }

            TemplateMatchModes matchMode = TemplateMatchModes.CCoeffNormed;
            switch (nccMethod)
            {
                case 0:
                    matchMode = TemplateMatchModes.SqDiff;
                    break;
                case 1:
                    matchMode = TemplateMatchModes.SqDiffNormed;
                    break;
                case 2:
                    matchMode = TemplateMatchModes.CCorr;
                    break;
                case 3:
                    matchMode = TemplateMatchModes.CCorrNormed;
                    break;
                case 4:
                    matchMode = TemplateMatchModes.CCoeff;
                    break;
                case 5:
                    matchMode = TemplateMatchModes.CCoeffNormed;
                    break;
            }

            //在没有旋转的情况下进行第一次匹配
            Cv2.MatchTemplate(src, model, result, matchMode);
            Cv2.MinMaxLoc(result, out double minVal, out double maxVal, out Point minLoc, out Point maxLoc, new Mat());

            Point location = maxLoc;
            double temp = maxVal;
            double angle = 0;

            Mat newImg;    

            //以最佳匹配点左右十倍角度步长进行循环匹配,直到角度步长小于参数角度步长
            if (nccMethod == 0 || nccMethod == 1)
            {
                do
                {
                    for (int i = 0; i <= (int)range / step; i++)
                    {
                        newImg = ImageRotate(model, start + step * i);
                        Cv2.MatchTemplate(src, newImg, result, matchMode);
                        Cv2.MinMaxLoc(result, out double minval, out double maxval, out Point minloc, out Point maxloc, new Mat());
                        if (maxval < temp)
                        {
                            location = maxloc;
                            temp = maxval;
                            angle = start + step * i;
                        }
                    }
                    range = step * 2;
                    start = angle - step;
                    step = step / 10;
                } while (step > angleStep);
                return new ResultPoint(location.X * Math.Pow(2, numLevels) + modelImage.Width / 2, location.Y * Math.Pow(2, numLevels) + modelImage.Height / 2, -angle, temp);
            }
            else
            {
                do
                {
                    for (int i = 0; i <= (int)range / step; i++)
                    {
                        newImg = ImageRotate(model, start + step * i);
                        Cv2.MatchTemplate(src, newImg, result, matchMode);
                        Cv2.MinMaxLoc(result, out double minval, out double maxval, out Point minloc, out Point maxloc, new Mat());
                        if (maxval > temp)
                        {
                            location = maxloc;
                            temp = maxval;
                            angle = start + step * i;
                        }
                    }
                    range = step * 2;
                    start = angle - step;
                    step = step / 10;
                } while (step > angleStep);
                if (temp > thresScore)
            {
                return new ResultPoint(location.X * Math.Pow(2, numLevels), location.Y * Math.Pow(2, numLevels), -angle, temp);
            }
            }
            return new ResultPoint();
        }

2/其他准备

            public ResultPoint(double x, double y, double t, double score)
            {
                X = (int)x;
                Y = (int)y;
                T = t;
                Score = score;
            }

            /// <summary>
            /// 图像旋转
            /// </summary>
            /// <param name="image">输入图像</param>
            /// <param name="angle">旋转的角度</param>
            /// <returns>旋转后图像</returns>
            static Mat ImageRotate(Mat image, double angle)
            {
                Mat newImg = new Mat();
                Point2f pt = new Point2f((float)image.Cols / 2, (float)image.Rows / 2);
                Mat r = Cv2.GetRotationMatrix2D(pt, angle, 1.0);
                Cv2.WarpAffine(image, newImg, r, image.Size());

                return newImg;
            }

            /// <summary>
            /// 金字塔下采样
            /// </summary>
            /// <param name="image">输入图像</param>
            /// <returns>下采样完图像</returns>
            private Mat ImagePyrDown(Mat image)
            {
                for (int i = 0; i < MyConfig.NumLevels; i++)
                {
                    Cv2.PyrDown(image, image, new Size(image.Cols / 2, image.Rows / 2));
                }

                return image;
            }

 

  • 15
    点赞
  • 193
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值