我正在使用 SURF 算法来查找查询图像和存储在数据库中的集合图像之间的相似性。为了获得更好的性能,我使用了快速近似最近邻 (FLANN)。现在,我想将这项工作分为两个步骤:
第一步:计算数据库中所有图像的描述符,然后将所有描述符组合成一个大矩阵,最后构建 FLANN。
第二步:计算查询图像的描述符,并使用 FLANN 索引查找查询描述符和所有集合描述符之间的匹配。
谁能帮我?
FLANN.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using Emgu.CV.GPU;
using Emgu.CV.Flann;
namespace flannconsole
{
class FLANN
{
private static double surfHessianThresh = 300;
private static bool surfExtendedFlag = true;
private static SURFDetector detector = new SURFDetector(surfHessianThresh, surfExtendedFlag);
public class IndecesMapping
{
public int IndexStart { get; set; }
public int IndexEnd { get; set; }
public int Similarity { get; set; }
public string fileName { get; set; }
public override string ToString()
{
return fileName + ": " + Similarity + "%";
}
}
public static IList<IndecesMapping> Match(string[] dbImages, string queryImage)
{
IList<IndecesMapping> imap;
// compute descriptors for each image
var dbDescsList = ComputeMultipleDescriptors(dbImages, out imap);
// concatenate all DB images descriptors into single Matrix
Matrix<float> dbDescs = ConcatDescriptors(dbDescsList);
// compute descriptors for the query image
Matrix<float> queryDescriptors = ComputeSingleDescriptors(queryImage);
FindMatches(dbDescs, queryDescriptors, ref imap);
return imap;
}
public static Matrix<float> ComputeSingleDescriptors(string fileName)
{
Matrix<float> descs;
using (Image<Gray, Byte> img = new Image<Gray, Byte>(fileName))
{
VectorOfKeyPoint keyPoints = detector.DetectKeyPointsRaw(img, null);
descs = detector.ComputeDescriptorsRaw(img, null, keyPoints);
}
return descs;
}
public static IList<Matrix<float>> ComputeMultipleDescriptors(string[] fileNames, out IList<IndecesMapping> imap)
{
imap = new List<IndecesMapping>();
IList<Matrix<float>> descs = new List<Matrix<float>>();
int r = 0;
for (int i = 0; i < fileNames.Length; i++)
{
var desc = ComputeSingleDescriptors(fileNames[i]);
descs.Add(desc);
imap.Add(new IndecesMapping()
{
fileName = fileNames[i],
IndexStart = r,
IndexEnd = r + desc.Rows - 1
});
r += desc.Rows;
}
return descs;
}
public static void FindMatches(Matrix<float> dbDescriptors, Matrix<float> queryDescriptors, ref IList<IndecesMapping> imap)
{
var indices = new Matrix<int>(queryDescriptors.Rows, 2);
var dists = new Matrix<float>(queryDescriptors.Rows, 2);
// create FLANN index with 4 kd-trees and perform KNN search over it look for 2 nearest neighbours
var flannIndex = new Index(dbDescriptors, 4);
flannIndex.KnnSearch(queryDescriptors, indices, dists, 2, 24);
for (int i = 0; i < indices.Rows; i++)
{
// filter out all inadequate pairs based on distance between pairs
if (dists.Data[i, 0] < (0.6 * dists.Data[i, 1]))
{
foreach (var img in imap)
{
if (img.IndexStart <= indices[i, 1] && img.IndexEnd >= indices[i, 1])
{
img.Similarity++;
break;
}
}
}
}
}
public static Matrix<float> ConcatDescriptors(IList<Matrix<float>> descriptors)
{
int cols = descriptors[0].Cols;
int rows = descriptors.Sum(a => a.Rows);
float[,] concatedDescs = new float[rows, cols];
int offset = 0;
foreach (var descriptor in descriptors)
{
// append new descriptors
Buffer.BlockCopy(descriptor.ManagedArray, 0, concatedDescs, offset, sizeof(float) * descriptor.ManagedArray.Length);
offset += sizeof(float) * descriptor.ManagedArray.Length;
}
return new Matrix<float>(concatedDescs);
}
}
}
程序.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using Emgu.CV.GPU;
using Emgu.CV.Flann;
namespace flannconsole
{
class Program
{
static void Main(string[] args)
{
string[] dbImages = Directory.GetFiles(@"E:/nf/");
string queryImage = "E://nf//01.jpg";
IList<FLANN.IndecesMapping> matches = FLANN.Match(dbImages, queryImage);
foreach (FLANN.IndecesMapping match in matches)
{
Console.WriteLine(match.ToString());
}
Console.ReadLine();
}
}
}