Emgu库是将OpenCV使用.net编程语言(C#)封装成的.net库。在实际软件开发中具有重要用途。
图像特征提取是从原始图像中提取对图像识别、分类、检索等任务有用的信息。这些特征通常具有对变换、光照、尺度等因素的不变性,从而使得后续任务更为稳定和可靠。
针对Emgu库中间不同版本之间Api函数差异大,而且目前缺少结合实际例子的Api学习,本文对Emgu原文档进行解读并配备实例进行演示。
官方文档阅读地址:https://emgu.com/wiki/index.php/Version_History#Emgu.CV-4.7.0
官方Github地址:https://github.com/emgucv/emgucv
早期版本下载链接:https://sourceforge.net/projects/emgucv/
EmGU库中的特征描述符一般是在EmGU.CV.Features2D和XFeatures2D这两个名称空间中,主要是图像用于二维特征检测、提取和匹配。在这两个库中有大家熟悉的 SIFT,ORB,MSER,HarrisLaplace等特征描述符,也包括 BFMatcher和FlannBasedMatcher等特征匹配算法,还有DrawKeypoints,DrawMatches等一些非常实用的方法。下面将给大家详细介绍一下这些类函数的使用。
命名空间:Emgu.CV.Features2D
构造函数:AgastFeatureDetector(
int threshold = 10,
bool nonmaxSuppression = true,
AgastFeatureDetector.Type type = AgastFeatureDetector.Type.OAST_9_16)
参数说明:
1)阈值threshold
数据类型:System.Int32
2)非极大值抑制 nonmaxSuppression
数据类型:System.Boolean
算法详解:
代码示例:
using Emgu.CV;
using Emgu.CV.XFeatures2D;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using System.Drawing;
//定义特征检测器和图像
Mat input=new Mat(img_path);
Mat output=new Mat();
AgastFeatureDetector detector=new AgastFeatureDetector(threshold:100,nonmaxSuppression:true);
//返回可迭代的MKeyPoint数组类
MKeyPoint[] modelKeyPoints = detector.Detect(input, null);
//利用Features2DToolbox中绘制DrawKeypoints函数绘制关键点
Features2DToolbox.DrawKeypoints(input, new VectorOfKeyPoint(modelKeyPoints), output, new Bgr(0, 0, 255));
CvInvoke.Imshow("out_img", output);
CvInvoke.WaitKey(0);
相关论文:
Adaptive and generic corner detection based on the accelerated segment test. In Proceedings of the European onference on Computer Vision (ECCV’10).`下载地址
命名空间:Emgu.CV.Features2D
构造函数:AKAZE(
AKAZE.DescriptorType descriptorType = AKAZE.DescriptorType.Mldb,
int descriptorSize = 0,
int descriptorChannels = 3,
float threshold = 0.001f,
int nOctaves = 4,
int nOctaveLayers = 4,
KAZE.Diffusivity diffusivity = KAZE.Diffusivity.PmG2
)
参数说明:
1)提取的描述符的类型descriptorType(可选)
数据类型: Emgu.CV.Features2D.AKAZE.DescriptorType
2)描述符的大小(以位为单位)descriptorSize
数据类型:System.Int32
3)描述符中的通道数 descriptorChannels
数据类型:System.Int32
4)检测器对接受点的响应阈值 threshold
数据类型:System.Single
5)图像的最大八度演变 nOctaves
数据类型:System.Int32
6)每个级别的默认子级别数 nOctaveLayers
数据类型:System.Int32
7)扩散系数类型 diffusivity
数据类型:Emgu.CV.Features2D.KAZE.Diffusivity
算法详解:
代码如下(示例):
同第一个方法,修改检测器
AKAZE detector = new AKAZE();
命名空间:Emgu.CV.Features2D
构造函数:FastFeatureDetector(
int threshold = 10,
bool nonmaxSupression = true,
FastFeatureDetector.DetectorType type = FastFeatureDetector.DetectorType.Type9_16
)
参数说明:同AgastFeatureDetector类
threshold 指中心像素和围绕该像素的圆上的像素的强度之差的阈值。
算法详解:
代码如下(示例):
同第一个方法,修改检测器
FastFeatureDetector detector = new FastFeatureDetector();
命名空间:Emgu.CV.Features2D
构造函数:GFTTDetector(
int maxCorners = 1000,
double qualityLevel = 0.01,
double minDistance = 1,
int blockSize = 3,
bool useHarrisDetector = false,
double k = 0.04
)
参数说明:
1)要检测的最大特征数 maxCorners
数据类型:System.Int32
2) 最大最小特征值的乘数;指定图像角点的最低可接受范围 qualityLevel
数据类型:System.Double
算法详解:
3)限制的,指定返回拐角之间可能的最小距离;使用欧几里得距离。minDistance
数据类型:System.Double
4)平均块的大小,传递给函数cvCornerMinEigenVal或cvCornerHarris blockSize
数据类型:System.Int32
5)如果为真,将使用Harris 角点检测器 useHarrisDetector
数据类型:System.Boolean
代码如下(示例):
同第一个方法,修改检测器
GFTTDetector detector = new GFTTDetector(maxCorners: 20);
命名空间:Emgu.CV.Features2D
构造函数:KAZE(
bool extended = false,
bool upright = false,
float threshold = 0.001f,
int octaves = 4,
int sublevels = 4,
KAZE.Diffusivity diffusivity = KAZE.Diffusivity.PmG2
)
参数说明:
1) 设置为启用扩展(128字节)描述符的提取 extended
数据类型:System.Boolean
2) 设置为启用直立描述符(非旋转不变)。upright
数据类型:System.Boolean
其他参数同上
代码如下(示例):
同第一个方法,修改检测器
KAZE detector = new KAZE();
命名空间:Emgu.CV.Features2D
构造函数:MSER(
int delta = 5,
int minArea = 60,
int maxArea = 14400,
double maxVariation = 0.25,
double minDiversity = 0.2,
int maxEvolution = 200,
double areaThreshold = 1.01,
double minMargin = 0.003,
int edgeBlurSize = 5
)
参数说明:
- delta
数据类型:System.Int32- 修剪小于最小/最大面积的区域 minArea /maxArea
数据类型:System.Int32- 修剪面积与其子面积相似的区域 maxVariation
数据类型:System.Double- 回溯到 cut off mser with diversity minDiversity
数据类型:System.Double- 对于彩色图像,进一步操作 maxEvolution
数据类型:System.Int32- 导致重新初始化的区域阈值 areaThreshold
数据类型:System.Double- 忽略太小的边距 minMargin
数据类型:System.Double- 边缘模糊的光圈大小 edgeBlurSize
数据类型:System.Int32
代码如下(示例):
同第一个方法,修改检测器
MSER detector = new MSER();
命名空间:Emgu.CV.Features2D
构造函数:ORB(
int numberOfFeatures = 500,
float scaleFactor = 1.2f,
int nLevels = 8,
int edgeThreshold = 31,
int firstLevel = 0,
int WTK_A = 2,
ORB.ScoreType scoreType = ORB.ScoreType.Harris,
int patchSize = 31,
int fastThreshold = 20
)
参数说明:
- 所需特征的数量 numberOfFeatures
数据类型:System.Int32- 用它来划分从一个金字塔级别到下一个级别的维度 scaleFactor
数据类型:System.Single- 比例金字塔中的级别数 nLevels
数据类型:System.Int32- 这些点应该离边界有多远 edgeThreshold
数据类型:System.Int32- 给出图像的级别。如果为1,则意味着我们还将查看图像。scaleFactor的倍数更大 firstLevel
数据类型:System.Int32- 描述符的每个单元使用了多少个随机点 WTK_A
数据类型:System.Int32- 块的大小patchSize
数据类型:System.Int32- FAST 阈值 fastThreshold
数据类型:System.Int32
代码如下(示例):
同第一个方法,修改检测器
ORB detector = new ORB();
命名空间:Emgu.CV.Features2D
构造函数:SIFT(
int nFeatures = 0,
int nOctaveLayers = 3,
double contrastThreshold = 0.04,
double edgeThreshold = 10,
double sigma = 1.6
)
参数说明:
- 所需特征数量,等于0不影响使用 nFeatures
数据类型:System.Int32- Octave层数。使用3作为默认值 nOctaveLayers
数据类型:System.Int32- 对比度阈值。使用0.04作为默认值 contrastThreshold
数据类型:System.Double- 检测器参数。使用10.0作为默认值 edgeThreshold
数据类型:System.Double
代码如下(示例):
同第一个方法,修改检测器
SIFT detector = new SIFT();
命名空间:Emgu.CV.Features2D
构造函数:SimpleBlobDetector(
SimpleBlobDetectorParams parameters = null
)
参数说明:
SimpleBlobDetectorParams SimpleBlob检测器的参数,用SimpleBlobDetectorParams定义
详细参数可以看这个链接Click
代码如下(示例):
同第一个方法,修改检测器
SimpleBlobDetectorParams blobDetectorParams = new SimpleBlobDetectorParams();
blobDetectorParams.blobColor = 255;
blobDetectorParams.MinThreshold = 0.2;
SimpleBlobDetector detector = new SimpleBlobDetector(blobDetectorParams);
命名空间:Emgu.CV.XFeatures2D
构造函数:StarDetector(
int maxSize = 45,
int responseThreshold = 30,
int lineThresholdProjected = 10,
int lineThresholdBinarized = 8,
int suppressNonmaxSize = 5
)
参数说明:
1)特征的最大尺寸。支持以下参数值:4、6、8、11、12、16、22、23、32、45、46、64、90、128 maxSize
数据类型:System.Int32
2) 阈值为近似拉普拉斯算子,用于消除弱特征。它越大,检索到的特征就越少responseThreshold
数据类型:System.Int32
3)拉普拉斯算子消除边缘的另一个阈值。阈值越大,你得到的点就越多lineThresholdProjected
数据类型:System.Int32
4)用于消除边缘的特征大小的另一个阈值。阈值越大,你得到的点就越多。lineThresholdBinarized
数据类型:System.Int32
5)抑制非最大的值 suppressNonmaxSize
数据类型:System.Int32
代码如下(示例):
同第一个方法,修改检测器
StarDetector detector=new StarDetector();
命名空间:Emgu.CV.XFeatures2D
构造函数:MSDDetector(
int patchRadius,
int searchAreaRadius,
int nmsRadius,
int nmsScaleRadius,
float thSaliency,
int kNN,
float scaleFactor,
int nScales,
bool computeOrientation
)
参数说明:
- patchRadius 数据类型:System.Int32
- searchAreaRadius 数据类型:System.Int32
- nmsRadius 数据类型:System.Int32
- nmsScaleRadius 数据类型:System.Int32
- thSaliency 数据类型:System.float
- kNN 数据类型:System.float
- scaleFactor 数据类型:System.Int32
- nScales 数据类型:System.Int32
- computeOrientation System.Boolean
代码如下(示例):
同第一个方法,修改检测器
MSDDetector detector = new MSDDetector(patchRadius: 3, searchAreaRadius: 5, nmsRadius: 5, nmsScaleRadius: 0, thSaliency: 250.0f, kNN: 4, scaleFactor: 1.25f, nScales: -1 , computeOrientation: false);
命名空间:Emgu.CV.XFeatures2D
构造函数:HarrisLaplaceFeatureDetector(
int numOctaves,
float cornThresh,
float DOGThresh,
int maxCorners,
int numLayers)
参数说明:
1)标度空间金字塔中的octaves 数量 numOctaves
数据类型:System.Int32
2)Harris 角度度量的阈值 cornThresh
System.float
3)高斯差量表选择的阈值 DOGThresh
System.float
4)要考虑的最大拐角数 maxCorners
数据类型:System.Int32
5)每octave的中间octave numLayers
代码如下(示例):
同第一个方法,修改检测器
HarrisLaplaceFeatureDetector detector = new HarrisLaplaceFeatureDetector(numOctaves:6,cornThresh:0.01f,DOGThresh:0.01f,maxCorners:5000,numLayers:4);
使用方式:
public BriefDescriptorExtractor(int descriptorSize = 32)
descriptorSize 描述符的大小。它可取16、32或64
使用方式:
public void Compute( IInputArray image, VectorOfKeyPoint keyPoints, IOutputArray descriptors ) 根据给定的关键点位置计算图像上的描述符
代码如下(示例):
using Emgu.CV;
using Emgu.CV.XFeatures2D;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using System.Drawing;
//定义特征检测器和图像
Mat input = new Mat(path);
Mat descriptors=new Mat();
AKAZE detector = new AKAZE();
//返回可迭代的MKeyPoint数组类
MKeyPoint[] modelKeyPoints = detector.Detect(input, null);
//利用Compute计算特征描述符 ,descriptors的大小为num_points*dim的二维特征矩阵
detector.Compute(input, new VectorOfKeyPoint(modelKeyPoints), descriptors);
CvInvoke.WaitKey(0);
使用方式:
public MKeyPoint[] Detect(IInputArray image, IInputArray mask = null) 返回图像中检测的关键点 ,
返回值类型为MKeyPoint,可迭代的对象,包括:Angle;ClassId;Octave;Point;Response ;Size 六个字段成员
使用方式:
public void DetectAndCompute( IInputArray image,
IInputArray mask,
VectorOfKeyPoint keyPoints,
IOutputArray descriptors,
bool useProvidedKeyPoints )
参数说明
1)image 输入图像 类型:Emgu.CV.IInputArray
2)mask 掩膜图像,不需要可选择null值 类型:Emgu.CV.IInputArray
3)keyPoints 检测到的关键点将存储在此矢量中 类型:Emgu.CV.Util.VectorOfKeyPoint
4)descriptors 关键点描述符 类型:Emgu.CV.IOutputArray
5)useProvidedKeyPoints 如果为true,则该方法将跳过检测阶段,并计算所提供关键点的描述符
使用方式:
public void DetectRaw( IInputArray image, VectorOfKeyPoint keypoints, IInputArray mask = null )
参数说明 同上
使用方式:
public BFMatcher( DistanceType distanceType, bool crossCheck = false)
参数说明
1)距离类型 distanceType
数据类型 Emgu.CV.Features2D.DistanceType
2)指定是否需要交叉检查。使用false作为默认值。crossCheck
数据类型:System.Boolean
代码如下(示例):
Mat mat_father = new Mat(path1);
Mat mat_son= new Mat(path2);
Mat father_descriper = new Mat();
Mat son_descriper = new Mat();
Mat result = new Mat();
VectorOfVectorOfDMatch matches_result = new VectorOfVectorOfDMatch();
KAZE detector = new KAZE();
BFMatcher matcher = new BFMatcher(DistanceType.L2);
MKeyPoint[] modelKeyPoints_father = detector.Detect(mat_father, null);
MKeyPoint[] modelKeyPoints_son = detector.Detect(mat_son, null);
detector.Compute(mat_father, new VectorOfKeyPoint(modelKeyPoints_father), father_descriper);
detector.Compute(mat_son, new VectorOfKeyPoint(modelKeyPoints_son), son_descriper);
matcher.KnnMatch(son_descriper, father_descriper, matches_result, k:2);
Features2DToolbox.DrawMatches(mat_father,
new VectorOfKeyPoint(modelKeyPoints_father),
mat_son,
new VectorOfKeyPoint(modelKeyPoints_son),
matches_result,
result,
new MCvScalar(0, 0, 125),
new MCvScalar(255, 255, 0),
null);
CvInvoke.Imshow("result", result);
CvInvoke.WaitKey(0);
使用方式:
public FlannBasedMatcher(
IIndexParams indexParams,
SearchParams search
)
定义参数
索引参数的类型 Flann.SearchParams searchpar = new .Flann.SearchParams();
搜索参数 Flann.KdTreeIndexParams indexpar=new Flann.KdTreeIndexParams(trees:5);
代码如下(示例):
修改匹配函数即可
Emgu.CV.Flann.SearchParams searchpar = new Emgu.CV.Flann.SearchParams();
Emgu.CV.Flann.KdTreeIndexParams indexpar = new Emgu.CV.Flann.KdTreeIndexParams(trees: 5);
FlannBasedMatcher matcher = new FlannBasedMatcher(indexpar, searchpar);
MKeyPoint[] modelKeyPoints_father = detector.Detect(mat_father, null);
MKeyPoint[] modelKeyPoints_son = detector.Detect(mat_son, null);
detector.Compute(mat_father, new VectorOfKeyPoint(modelKeyPoints_father), father_descriper);
detector.Compute(mat_son, new VectorOfKeyPoint(modelKeyPoints_son), son_descriper);
matcher.Add(father_descriper);
matcher.KnnMatch(son_descriper, matches,k);
Features2DToolbox.DrawMatches(mat_father,
new VectorOfKeyPoint(modelKeyPoints_father),
mat_son,
new VectorOfKeyPoint(modelKeyPoints_son),
matches_result,
result,
new MCvScalar(0, 0, 125),
new MCvScalar(255, 255, 0),
null);
CvInvoke.Imshow("result", result);
CvInvoke.WaitKey(0);
`在本文中,我们对Emgu最新版本中关于特征点检测,提取以及匹配的算法进行注释说明,并配备了实例演示代码,不足之处,望请指正。