OpenCVSharp:了解几种特征检测

前言

前面已经介绍过了OpenCVSharp中封装的几个特征检测算法,其实里面还有很多特征检测算法,不再一篇一篇地介绍了,其它的都放在这一篇,简单过一下,有点印象即可。

FAST特征检测

FAST(Features from Accelerated Segment Test)是一种高效的特征点检测算法,它通过比较候选像素点周围圆形区域上连续像素的强度差异来识别角点特征。该算法的核心思想是:如果某个像素点周围有足够多的连续像素比该点亮或暗足够大的阈值,则认为该点是一个特征点。FAST算法以其计算速度快、实现简单而著称,特别适合需要实时处理的应用场景,如视频跟踪、SLAM(同步定位与地图构建)和增强现实等。相比SIFT、SURF等复杂特征检测算法,FAST在保持较好检测效果的同时,大幅提升了处理速度,使其成为计算机视觉领域中广泛使用的基础特征检测方法之一。

 // 读取图像
 using Mat imgSrc = new Mat(ImagePath, ImreadModes.Color);
 using Mat imgGray = new Mat();
 using Mat imgDst = imgSrc.Clone();
 
 // 转换为灰度图像
 Cv2.CvtColor(imgSrc, imgGray, ColorConversionCodes.BGR2GRAY, 0);

 // 使用FAST算法检测特征点
 // 参数说明:输入图像、阈值、是否启用非极大值抑制
 KeyPoint[] keypoints = Cv2.FAST(imgGray, 50, true);

 // 在图像上绘制检测到的特征点
 foreach (KeyPoint kp in keypoints)
 {
     imgDst.Circle((Point)kp.Pt, 3, Scalar.Red, -1, LineTypes.AntiAlias, 0);
 }

其过程就是读取图像、图像灰度化、FAST特征检测与绘制特征点。

现在来看下FAST方法:

public static KeyPoint[] FAST(InputArray image, int threshold, bool nonmaxSupression = true)
{
    if (image == null)
    {
        throw new ArgumentNullException("image");
    }

    image.ThrowIfDisposed();
    using VectorOfKeyPoint vectorOfKeyPoint = new VectorOfKeyPoint();
    NativeMethods.HandleException(NativeMethods.features2d_FAST1(image.CvPtr, vectorOfKeyPoint.CvPtr, threshold, nonmaxSupression ? 1 : 0));
    GC.KeepAlive(image);
    return vectorOfKeyPoint.ToArray();
}

这是OpenCvSharp库中FAST特征检测算法的核心实现函数,用于在灰度图像中快速检测角点特征。

参数名 类型 含义 默认值 说明
image InputArray 输入的灰度图像 必须是灰度图像,用于检测角点特征
threshold int 强度差异阈值 中心像素与周围圆形区域像素的强度差异阈值,值越大检测到的特征点越少但更稳定
nonmaxSupression bool 非极大值抑制 true 是否对检测到的角点应用非极大值抑制,启用后会消除重复或相近的角点

这样就可以得到一组特征点,如下所示:

绘制出来,如下所示:

FREAK特征检测

FREAK(Fast Retina Keypoint)是一种受人类视网膜视觉系统启发的快速二进制特征描述符,它通过模仿视网膜神经细胞的密集中心-稀疏周围的采样模式来提取图像局部特征。该算法首先使用其他关键点检测器(如ORB、FAST等)定位图像中的显著点,然后在这些点周围构建一个类似视网膜结构的采样模式,通过比较不同采样区域间的像素强度对来生成紧凑的二进制描述符。FREAK描述符具有计算效率高、内存占用小、匹配速度快的特点,同时对旋转、尺度变化和光照变化具有良好的鲁棒性,使其广泛应用于实时图像匹配、物体识别、视觉SLAM和增强现实等计算机视觉任务中。

  // 读取图像
  using var gray = new Mat(ImagePath, ImreadModes.Grayscale);
  using var dst = new Mat(ImagePath, ImreadModes.Color);

  // ORB检测关键点
  using var orb = ORB.Create(1000);
  KeyPoint[] keypoints = orb.Detect(gray);

  // FREAK计算描述符
  using var freak = FREAK.Create();
  Mat freakDescriptors = new Mat();
  freak.Compute(gray, ref keypoints, freakDescriptors);

  // 在图像上绘制检测到的特征点
  if (keypoints != null)
  {
      var color = new Scalar(0, 255, 0);
      foreach (KeyPoint kpt in keypoints)
      {
          float r = kpt.Size / 2;
          Cv2.Circle(dst, (Point)kpt.Pt, (int)r, color);
          Cv2.Line(dst,
              (Point)new Point2f(kpt.Pt.X + r, kpt.Pt.Y + r),
              (Point)new Point2f(kpt.Pt.X - r, kpt.Pt.Y - r),
              color);
          Cv2.Line(dst,
              (Point)new Point2f(kpt.Pt.X - r, kpt.Pt.Y + r),
              (Point)new Point2f(kpt.Pt.X + r, kpt.Pt.Y - r),
              color);
      }
  }

先用ORB检测关键点,然后再用FREAK特征检测。

来看下FREAK.Create方法的签名:

 public static FREAK Create(
     bool orientationNormalized = true,
     bool scaleNormalized = true,
     float patternScale = 22.0f,
     int nOctaves = 4,
     IEnumerable<int>? selectedPairs = null)

这个函数是OpenCV中FREAK特征描述符的工厂方法,用于创建和配置FREAK描述符实例。

查看参数含义:

参数名 类型 默认值 含义说明
orientationNormalized bool true 启用方向归一化,使描述符对图像旋转具有不变性
scaleNormalized bool true 启用尺度归一化,使描述符对图像缩放具有不变性
patternScale float 22.0f 描述符模式的缩放因子,控制采样模式的整体大小
nOctaves int 4 检测关键点覆盖的八度组数量,决定尺度范围
selectedPairs IEnumerable? null 用户自定义的采样对集合,可优化性能或适应特定场景

再来看下Compute方法的签名:

 public virtual void Compute(InputArray image, ref KeyPoint[] keypoints, OutputArray descriptors)

该函数接收输入图像和关键点数组,为每个关键点计算对应的特征描述符,并返回描述符矩阵。

效果:

KAZE/AKAZE特征检测

KAZE和AKAZE是两种先进的图像特征检测算法,用于识别图像中的关键点并提取其描述符。KAZE(Keyframes of Accelerated Speeded-up Robust Features)采用非线性尺度空间构建方法,通过非线性扩散滤波来检测特征点,对图像模糊和噪声具有出色的鲁棒性。AKAZE(Accelerated-KAZE)是KAZE的优化版本,使用快速显式扩散(FED)算法显著提高了计算速度,同时保持了特征检测的质量。这两种算法都能在旋转、缩放和亮度变化等条件下稳定地检测特征点,广泛应用于图像匹配、物体识别、三维重建和增强现实等计算机视觉任务中。

 // 创建KAZE和AKAZE特征检测器
using var kaze = KAZE.Create();
using var akaze = AKAZE.Create();

var kazeDescriptors = new Mat();
var akazeDescriptors = new Mat();
KeyPoint[] kazeKeyPoints = null, akazeKeyPoints = null;

// 测量KAZE处理时间
var kazeTime = MeasureTime(() =>
   kaze.DetectAndCompute(gray, null, out kazeKeyPoints, kazeDescriptors));

// 测量AKAZE处理时间
var akazeTime = MeasureTime(() =>
   akaze.DetectAndCompute(gray, null, out akazeKeyPoints, akazeDescriptors));

// 创建结果图像
var dstKaze = new Mat();
var dstAkaze = new Mat();

// 读取彩色图像用于绘制特征点
using var colorImage = new Mat(ImagePath, ImreadModes.Color);

// 绘制KAZE特征点
Cv2.DrawKeypoints(colorImage, kazeKeyPoints, dstKaze);

// 绘制AKAZE特征点
Cv2.DrawKeypoints(colorImage, akazeKeyPoints, dstAkaze)

查看KAZE.Create函数签名:

 public static KAZE Create(
   bool extended = false, bool upright = false, float threshold = 0.001f,
   int nOctaves = 4, int nOctaveLayers = 4, KAZEDiffusivityType diffusivity = KAZEDiffusivityType.DiffPmG2)

这是OpenCV中KAZE特征检测器的工厂方法实现,用于创建和配置KAZE算法实例。

参数名 参数含义 默认值
extended 是否启用扩展描述符(128字节) false
upright 是否使用直立描述符(非旋转不变) false
threshold 检测器响应阈值 0.001f
nOctaves 图像最大金字塔层数 4
nOctaveLayers 每个尺度层的子级别数量 4
diffusivity 扩散类型(DIFF_PM_G1, DIFF_PM_G2, DIFF_WEICKERT, DIFF_CHARBONNIER) KAZEDiffusivityType.DiffPmG2

查看AKAZE.Create函数签名:

public static AKAZE Create(AKAZEDescriptorType descriptorType = AKAZEDescriptorType.MLDB, int descriptorSize = 0, int descriptorChannels = 3, float threshold = 0.001f, int nOctaves = 4, int nOctaveLayers = 4, KAZEDiffusivityType diffusivity = KAZEDiffusivityType.DiffPmG2)

这是OpenCV中AKAZE特征检测器的工厂方法实现,用于创建和配置AKAZE算法实例。AKAZE(Accelerated-KAZE)是KAZE算法的加速版本,通过快速显式扩散(FED)算法提高了计算速度。

参数名 参数含义
descriptorType 描述符类型(DESCRIPTOR_KAZE, DESCRIPTOR_KAZE_UPRIGHT, DESCRIPTOR_MLDB, DESCRIPTOR_MLDB_UPRIGHT)
descriptorSize 描述符的位数(0表示完整大小)
descriptorChannels 描述符中的通道数(1, 2, 3)
threshold 检测器响应阈值
nOctaves 图像最大金字塔层数
nOctaveLayers 每个尺度层的子级别数量
diffusivity 扩散类型(DIFF_PM_G1, DIFF_PM_G2, DIFF_WEICKERT, DIFF_CHARBONNIER)

查看DrawKeypoints函数签名:

 public static void DrawKeypoints(
   InputArray image,
   IEnumerable<KeyPoint> keypoints, 
   InputOutputArray outImage,
   Scalar? color = null,
   DrawMatchesFlags flags = DrawMatchesFlags.Default)

这个函数是OpenCV中用于在图像上绘制特征点的静态方法。它接受源图像和检测到的关键点列表,然后在输出图像上可视化这些特征点。

参数名 参数含义
image 源图像
keypoints 从源图像中检测到的关键点集合
outImage 输出图像,其内容取决于flags参数定义的绘制方式
color 特征点的颜色,默认为null表示使用随机颜色
flags 绘制特征的标志,由DrawMatchesFlags枚举定义,控制特征点的绘制样式

效果:

Star特征检测

Star特征检测是一种基于图像强度的特征点检测算法,它通过在不同尺度上寻找图像中的"星形"结构来识别关键点。该算法使用多尺度分析技术,能够检测不同大小的特征点,对图像中的角点和斑点都很敏感。Star检测器的工作原理是首先将图像转换为灰度图,然后通过计算每个像素点在不同尺度下的响应值来识别具有显著特征的点,最后应用非极大值抑制来筛选出最优的特征点。这种检测器特别适用于图像配准、物体识别、三维重建和图像拼接等计算机视觉应用,因为它能够提供稳定且可重复的特征点,即使在图像发生尺度变化或轻微旋转时也能保持较好的检测效果。

 // 读取图像
using Mat imgSrc = new Mat(ImagePath, ImreadModes.Color);
using Mat imgGray = new Mat();
using Mat imgDst = imgSrc.Clone();

// 转换为灰度图像
Cv2.CvtColor(imgSrc, imgGray, ColorConversionCodes.BGR2GRAY, 0);

// 使用StarDetector算法检测特征点
StarDetector detector = StarDetector.Create(MaxSize, ResponseThreshold, LineThresholdProjected, 
                                        LineThresholdBinarized, SuppressNonmaxSize);
KeyPoint[] keypoints = detector.Detect(imgGray);

// 在图像上绘制检测到的特征点
if (keypoints != null)
{
   var color = new Scalar(0, 255, 0); // 绿色
   foreach (KeyPoint kpt in keypoints)
   {
       float r = kpt.Size / 2;
       Cv2.Circle(imgDst, (Point)kpt.Pt, (int)r, color);
       Cv2.Line(imgDst,
           (Point)new Point2f(kpt.Pt.X + r, kpt.Pt.Y + r),
           (Point)new Point2f(kpt.Pt.X - r, kpt.Pt.Y - r),
           color);
       Cv2.Line(imgDst,
           (Point)new Point2f(kpt.Pt.X - r, kpt.Pt.Y + r),
           (Point)new Point2f(kpt.Pt.X + r, kpt.Pt.Y - r),
           color);
   }
}

使用过程就是读取图像、转换为灰度图像、使用StarDetector算法检测特征点与在图像上绘制检测到的特征点。

查看StarDetector.Create函数签名:

public static StarDetector Create(
  int maxSize = 45, 
  int responseThreshold = 30, 
  int lineThresholdProjected = 10, 
  int lineThresholdBinarized = 8,
  int suppressNonmaxSize = 5)

这个函数是 OpenCV 中 StarDetector 类的静态工厂方法,用于创建一个 Star 特征检测器的实例。

参数名 默认值 含义
maxSize 45 控制检测的最大特征点尺寸,较大的值可以检测更大的特征结构
responseThreshold 30 响应阈值,用于过滤掉响应值低于此阈值的特征点,提高检测质量
lineThresholdProjected 10 投影线阈值,用于控制线状结构的检测灵敏度
lineThresholdBinarized 8 二值化线阈值,进一步细化线状特征的检测标准
suppressNonmaxSize 5 非极大值抑制的邻域大小,用于在局部区域内保留最强的特征点

效果:

posted @ 2025-12-15 13:39  mingupupup  阅读(144)  评论(0)    收藏  举报