Welcome

首页 / 软件开发 / .NET编程技术 / 图像特征检测(Image Feature Detection)(三)

图像特征检测(Image Feature Detection)(三)2011-05-06 博客园 王先荣SiftDetector类的实现代码如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
using Emgu.CV;
using Emgu.CV.Structure;
namespace ImageProcessLearn
{
/// <summary>
/// SIFT检测器
/// </summary>
public class SiftDetector : IDisposable
{
//成员变量
private IntPtr ptrSiftFilt;
//属性
/// <summary>
/// SiftFilt指针
/// </summary>
public IntPtr PtrSiftFilt
{
get
{
return ptrSiftFilt;
}
}
/// <summary>
/// 获取SIFT检测器中的SiftFilt
/// </summary>
public VlSiftFilt SiftFilt
{
get
{
return (VlSiftFilt)Marshal.PtrToStructure (ptrSiftFilt, typeof(VlSiftFilt));
}
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="width">图像的宽度</param>
/// <param name="height">图像的高度</param>
/// <param name="noctaves">阶数</param>
/// <param name="nlevels">每一阶的层数 </param>
/// <param name="o_min">最小阶的索引 </param>
public SiftDetector(int width, int height, int noctaves, int nlevels, int o_min)
{
ptrSiftFilt = VlFeatInvoke.vl_sift_new(width, height, noctaves, nlevels, o_min);
}
public SiftDetector(int width, int height)
: this(width, height, 4, 2, 0)
{ }
public SiftDetector(Size size, int noctaves, int nlevels, int o_min)
: this(size.Width, size.Height, noctaves, nlevels, o_min)
{ }
public SiftDetector(Size size)
: this(size.Width, size.Height, 4, 2, 0)
{ }
/// <summary>
/// 进行SIFT检测,并返回检测的结果
/// </summary>
/// <param name="im">单通道浮点型图像数据,图像数据不 必归一化到区间[0,1]</param>
/// <param name="resultType">SIFT检测的结果类型 </param>
/// <returns>返回SIFT检测结果——SIFT特征列表;如果检 测失败,返回null。</returns>
unsafe public List<SiftFeature> Process(IntPtr im, SiftDetectorResultType resultType)
{
//定义变量
List<SiftFeature> features = null; //检测结果:SIFT特征列表
VlSiftFilt siftFilt; //
VlSiftKeypoint* pKeyPoints; //指向关键点的指针
VlSiftKeypoint keyPoint; //关键点
SiftKeyPointOrientation[] orientations; //关键点对 应的方向及描述
double[] angles = new double[4]; //关键点对应的方向(角度)
int angleCount; //某个关键点的方向数目
double angle; //方向
float[] descriptors; //关键点某个方向的描述
IntPtr ptrDescriptors = Marshal.AllocHGlobal(128 * sizeof(float)); //指向描述的缓冲区指针
//依次遍历每一阶
if (VlFeatInvoke.vl_sift_process_first_octave (ptrSiftFilt, im) != VlFeatInvoke.VL_ERR_EOF)
{
features = new List<SiftFeature> (100);
while (true)
{
//计算每组中的关键点
VlFeatInvoke.vl_sift_detect (ptrSiftFilt);
//遍历每个点
siftFilt = (VlSiftFilt) Marshal.PtrToStructure(ptrSiftFilt, typeof(VlSiftFilt));
pKeyPoints = (VlSiftKeypoint*) siftFilt.keys.ToPointer();
for (int i = 0; i < siftFilt.nkeys; i++)
{
keyPoint = *pKeyPoints;
pKeyPoints++;
orientations = null;
if (resultType == SiftDetectorResultType.Normal || resultType == SiftDetectorResultType.Extended)
{
//计算并遍历每个点的 方向
angleCount = VlFeatInvoke.vl_sift_calc_keypoint_orientations(ptrSiftFilt, angles, ref keyPoint);
orientations = new SiftKeyPointOrientation[angleCount];
for (int j = 0; j < angleCount; j++)
{
angle = angles[j];
descriptors = null;
if (resultType == SiftDetectorResultType.Extended)
{
//计 算每个方向的描述
VlFeatInvoke.vl_sift_calc_keypoint_descriptor(ptrSiftFilt, ptrDescriptors, ref keyPoint, angle);
descriptors = new float[128];
Marshal.Copy(ptrDescriptors, descriptors, 0, 128);
}
orientations [j] = new SiftKeyPointOrientation(angle, descriptors); //保存关键点方向和 描述
}
}
features.Add(new SiftFeature(keyPoint, orientations)); //将得到的特征添加到列表中
}
//下一阶
if (VlFeatInvoke.vl_sift_process_next_octave(ptrSiftFilt) == VlFeatInvoke.VL_ERR_EOF)
break;
}
}
//释放资源
Marshal.FreeHGlobal(ptrDescriptors);
//返回
return features;
}
/// <summary>
/// 进行基本的SIFT检测,并返回关键点列表
/// </summary>
/// <param name="im">单通道浮点型图像数据,图像数据不 必归一化到区间[0,1]</param>
/// <returns>返回关键点列表;如果获取失败,返回null。 </returns>
public List<SiftFeature> Process(IntPtr im)
{
return Process(im, SiftDetectorResultType.Basic);
}
/// <summary>
/// 进行SIFT检测,并返回检测的结果
/// </summary>
/// <param name="image">图像</param>
/// <param name="resultType">SIFT检测的结果类型 </param>
/// <returns>返回SIFT检测结果——SIFT特征列表;如果检 测失败,返回null。</returns>
public List<SiftFeature> Process(Image<Gray, Single> image, SiftDetectorResultType resultType)
{
if (image.Width != SiftFilt.width || image.Height != SiftFilt.height)
throw new ArgumentException("图像的尺寸和构 造函数中指定的尺寸不一致。", "image");
return Process(image.MIplImage.imageData, resultType);
}
/// <summary>
/// 进行基本的SIFT检测,并返回检测的结果
/// </summary>
/// <param name="image">图像</param>
/// <returns>返回SIFT检测结果——SIFT特征列表;如果检 测失败,返回null。</returns>
public List<SiftFeature> Process(Image<Gray, Single> image)
{
return Process(image, SiftDetectorResultType.Basic);
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (ptrSiftFilt != IntPtr.Zero)
VlFeatInvoke.vl_sift_delete(ptrSiftFilt);
}
}
/// <summary>
/// SIFT特征
/// </summary>
public struct SiftFeature
{
public VlSiftKeypoint keypoint; //关键点
public SiftKeyPointOrientation[] keypointOrientations; //关键点的方向及方向对应的描述
public SiftFeature(VlSiftKeypoint keypoint)
: this(keypoint, null)
{
}
public SiftFeature(VlSiftKeypoint keypoint, SiftKeyPointOrientation[] keypointOrientations)
{
this.keypoint = keypoint;
this.keypointOrientations = keypointOrientations;
}
}
/// <summary>
/// Sift关键点的方向及描述
/// </summary>
public struct SiftKeyPointOrientation
{
public double angle; //方向
public float[] descriptors; //描述
public SiftKeyPointOrientation(double angle)
: this(angle, null)
{
}
public SiftKeyPointOrientation(double angle, float[] descriptors)
{
this.angle = angle;
this.descriptors = descriptors;
}
}
/// <summary>
/// SIFT检测的结果
/// </summary>
public enum SiftDetectorResultType
{
Basic, //基本:仅包含关键点
Normal, //正常:包含关键点、方向
Extended //扩展:包含关键点、方向以及描述
}
}