我正在开展一个项目,以从图像集合中识别(相似度百分比)图像。我使用了 EmugCV 3.1.0。代码如下。虽然程序运行,但它有以下问题
- 当匹配找到始终显示第一张图像的百分比时。找到附件
如果我们将相同的图像两次放入 dbimage 集合中,并将相同的图像作为查询图像,则所有匹配百分比为零。找到附件
字符串[] dbImages = { imgPath + "1.jpg", imgPath + "2.jpg", imgPath + "3.jpg", imgPath + "4.jpg" }; 字符串 queryImage = imgPath + "4.jpg";
在这些图像中,图像“2”和“4”是相同的
代码如下
public partial class Form1 : Form
{
private static double surfHessianThresh = 300;
private static SURF detector;
public Form1()
{
InitializeComponent();
ImageMatching();
}
public void ImageMatching()
{
string MatchString = null;
detector = new SURF(surfHessianThresh);
IList<IndecesMapping> matches = Match();
IOrderedEnumerable<IndecesMapping> orderedMatches = matches.OrderByDescending(match => match.Similarity);
foreach (IndecesMapping match in orderedMatches)
{
MatchString = MatchString + "\n" + match.ToString();
}
lblMatch.Text = MatchString;
//Console.WriteLine();
//Console.WriteLine("MOST LIKELY MATCH: " + orderedMatches.First());
//Console.WriteLine("Press enter to exit...");
//Console.ReadLine();
}
/// <summary>
/// Main method.
/// </summary>
static public IList<IndecesMapping> Match()
{
string imgPath = "E:\\Riyas\\Projects\\Image Recognition\\Sample Projects\\EmguSample3.1.0\\EmguSample3.1.0\\";
string[] dbImages = { imgPath + "1.jpg", imgPath + "2.jpg", imgPath + "3.jpg", imgPath + "4.jpg" };
string queryImage = imgPath + "1.jpg";
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;
}
/// <summary>
/// Computes image descriptors.
/// </summary>
/// <param name="fileName">Image filename.</param>
/// <returns>The descriptors for the given image.</returns>
static public Matrix<float> ComputeSingleDescriptors(string fileName)
{
Matrix<float> descs = null;
using (Image<Gray, Byte> img = new Image<Gray, byte>(fileName))
{
MKeyPoint[] mkeyPoints = detector.Detect(img, null);
VectorOfKeyPoint keyPoints = new VectorOfKeyPoint();
keyPoints.Push(mkeyPoints);
UMat observedDescriptors = new UMat();
detector.Compute(img, keyPoints, observedDescriptors);
descs = new Matrix<float>(observedDescriptors.Size);
detector.Compute(img, keyPoints, descs);
}
return descs;
}
/// <summary>
/// Convenience method for computing descriptors for multiple images.
/// On return imap is filled with structures specifying which descriptor ranges in the concatenated matrix belong to what image.
/// </summary>
/// <param name="fileNames">Filenames of images to process.</param>
/// <param name="imap">List of IndecesMapping to hold descriptor ranges for each image.</param>
/// <returns>List of descriptors for the given images.</returns>
static public 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;
}
/// <summary>
/// Computes 'similarity' value (IndecesMapping.Similarity) for each image in the collection against our query image.
/// </summary>
/// <param name="dbDescriptors">Query image descriptor.</param>
/// <param name="queryDescriptors">Consolidated db images descriptors.</param>
/// <param name="images">List of IndecesMapping to hold the 'similarity' value for each image in the collection.</param>
static public void FindMatches(Matrix<float> dbDescriptors, Matrix<float> queryDescriptors, ref IList<IndecesMapping> imap)
{
var indices = new Matrix<int>(queryDescriptors.Rows, 2); // matrix that will contain indices of the 2-nearest neighbors found
var dists = new Matrix<float>(queryDescriptors.Rows, 2); // matrix that will contain distances to the 2-nearest neighbors found
// create FLANN index with 4 kd-trees and perform KNN search over it look for 2 nearest neighbours
KdTreeIndexParamses kdparam = new KdTreeIndexParamses(4);
var flannIndex = new Index(dbDescriptors, kdparam);
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]))
{
// find image from the db to which current descriptor range belongs and increment similarity value.
// in the actual implementation this should be done differently as it's not very efficient for large image collections.
foreach (var img in imap)
{
if (img.IndexStart <= i && img.IndexEnd >= i)
{
img.Similarity++;
break;
}
}
}
}
}
/// <summary>
/// Concatenates descriptors from different sources (images) into single matrix.
/// </summary>
/// <param name="descriptors">Descriptors to concatenate.</param>
/// <returns>Concatenated matrix.</returns>
static public 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);
}
}
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 + "%";
}
}