文章目录

说明

1、EmguCV中Harris角点检测函数:CvInvoke.CornerHarris()
参数harrisResponse为CV_32FC1的图像,计算后需要进行归一化或者阈值化,转换为CV8U再显示;
参数blockSize : 领域大小,和协方差矩阵M的计算有关(影响M的值)

2、Harris检测的结果衡量(角点响应度量):M为协方差矩阵,度量R判断是否为角点,需要自己选择判断合适的阈值;

3、Shi-Tomasi角点检测:EmguCV没有封装goodFeatureToTrack()方法,只能使用GFTTDetector类的Detect()方法来检测特征点;可以自己控制想要的角点数,使用更方便;
参数minDistance控制角点之间的距离;

4、亚像素级角点检测:cornerSubPix()

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.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using System.Drawing;
using Emgu.CV.Features2D;

namespace lesson31
{
   
    class Program
    {
   
        static void Main(string[] args)
        {
   
            ///Harris角点检测
            //Mat src = CvInvoke.Imread("3.jpg");
            //CvInvoke.Imshow("input", src);
            //Mat gray = new Mat();
            //CvInvoke.CvtColor(src, gray, ColorConversion.Bgr2Gray);
            //Mat dst = new Mat();
            //CvInvoke.CornerHarris(gray, dst, 2, 3, 0.04);//角点检测
            //CvInvoke.Threshold(dst, dst, 0.005, 255, ThresholdType.Binary);
            //Console.WriteLine("Depth: {0}\nChannels: {1}", dst.Depth, dst.NumberOfChannels);
            //dst.ConvertTo(dst, DepthType.Cv8U);
            //CvInvoke.Imshow("CornerHarris", dst);
            //Image<Gray, Byte> img = dst.ToImage<Gray, Byte>();
            //for (int i = 0; i < img.Rows; i++)
            //{
   
            // for (int j = 0; j < img.Cols; j++)
            // {
   
            // if (img.Data[i, j, 0] == 255)
            // {
   
            // CvInvoke.Circle(src, new Point(j, i), 2, new MCvScalar(0, 255, 0), -1);
            // }
            // }
            //}
            //CvInvoke.Imshow("result", src);
            //CvInvoke.WaitKey(0);

            ///另一种方法
            //Mat src = CvInvoke.Imread("3.jpg");
            //Mat grayImg = new Mat();
            //CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);

            //Mat dst = new Mat();
            //CvInvoke.CornerHarris(grayImg, dst, 2, 3, 0.04, BorderType.Default);
            //Mat scaleImg = new Mat();
            //CvInvoke.Normalize(dst, dst, 0, 255, NormType.MinMax, DepthType.Cv32F);
            //CvInvoke.ConvertScaleAbs(dst, scaleImg, 1, 0);
            //Image<Gray, Byte> img = scaleImg.ToImage<Gray, Byte>();
            //for(int i = 0; i < img.Rows;i++)
            //{
   
            // for(int j =0; j < img.Cols; j++)
            // {
   
            // if(img.Data[i,j,0] > 100) //阈值选取很重要,控制角点个数
            // {
   
            // CvInvoke.Circle(src, new Point(j, i), 3, new MCvScalar(0, 255, 0), -1);
            // }
            // }
            //}
            //CvInvoke.Imshow("result", src);
            //CvInvoke.WaitKey(0);

            ///Shi-Tomasi角点检测
            //Mat src = CvInvoke.Imread("mask2.jpg");
            //Mat grayImg = new Mat();
            //CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
            //GFTTDetector gFTT = new GFTTDetector(12, 0.01, 1, 3, false, 0.04);
            //MKeyPoint[] points = gFTT.Detect(grayImg); //使用Shi-Tomasi检测算法检测特征点
            //for(int i = 0; i < points.Length; i++)
            //{
   
            // Point pt = new Point();
            // pt.X = (int)points[i].Point.X;
            // pt.Y = (int)points[i].Point.Y;

            // CvInvoke.Circle(src, pt, 3, new MCvScalar(0, 0, 255), -1);
            //}
            //CvInvoke.Imshow("result", src);
            //CvInvoke.WaitKey(0);

            ///亚像素角点检测
            Mat src = CvInvoke.Imread("3.jpg");
            CvInvoke.Imshow("input", src);

            Mat grayImg = new Mat();
            CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
            Mat harrisImg = new Mat();
            CvInvoke.CornerHarris(grayImg, harrisImg, 2, 3, 0.04);
            CvInvoke.Threshold(harrisImg, harrisImg, 0.01, 255, ThresholdType.Binary);
            Mat dst = new Mat();
            harrisImg.ConvertTo(dst, DepthType.Cv8U);
            CvInvoke.Imshow("mask", dst);


            VectorOfPointF corners = new VectorOfPointF();
            Image<Gray, Byte> img = dst.ToImage<Gray, Byte>();
            for(int i = 0; i < img.Rows; i++)
            {
   
                for(int j = 0; j < img.Cols; j++)
                {
   
                    if(img.Data[i,j,0] == 255)
                    {
   
                        CvInvoke.Circle(src, new Point(j, i), 3, new MCvScalar(0, 0, 255), -1);
                        PointF[] pt = new PointF[1];
                        pt[0].X = j;
                        pt[0].Y = i;
                        corners.Push(pt);
                    }
                }
            }
            CvInvoke.Imshow("result", src);
            MCvTermCriteria termCriteria = new MCvTermCriteria(40, 0.001);
            CvInvoke.CornerSubPix(grayImg, corners, new Size(5, 5), new Size(-1, -1), termCriteria); //亚像素级角点精确化
            for(int i = 0; i < corners.Size; i++)
            {
   
                Console.WriteLine("corner {0} : ({1:F2},{1:F2})", i, corners[i].X, corners[i].Y);
            }

            CvInvoke.WaitKey(0);
        }
    }
}

效果

1、Harris角点检测:

使用不同阈值,检测到的角点数也不同:

2、Shi-Tomasi检测:(GFTTDetector)

3、亚像素级角点精确化: