匹配图像并使用 SURF 确定最佳匹配
Matching image and determine best match using SURF
我一直在尝试使用 EMGU Example SURFFeature 来确定图像是否在图像集合中。但是我在理解如何确定是否找到匹配项时遇到了问题。
.........原图......................Scene_1(匹配)......................Scene_2(不匹配)
.....................
......................
我一直在查看文档并花了数小时寻找可能的解决方案,以了解如何确定图像是否相同。
正如您在下面的图片中看到的,两者都找到了匹配项。
很明显,我要查找的匹配项(连接线)更多,但我如何在代码中检查这一点?
问:如何筛选出好的匹配项?
我的目标是能够将输入图像(从网络摄像头捕获)与数据库中的图像集合进行比较。但在我可以将所有图像保存到数据库之前,我需要知道我可以将输入与哪些值进行比较。 (例如将对象关键点保存在数据库中)
这是我的示例代码(匹配部分):
private void match_test()
{
long matchTime;
using (Mat modelImage = CvInvoke.Imread(@"images\input.jpg", LoadImageType.Grayscale))
using (Mat observedImage = CvInvoke.Imread(@"images.jpg", LoadImageType.Grayscale))
{
Mat result = DrawMatches.Draw(modelImage, observedImage, out matchTime);
//ImageViewer.Show(result, String.Format("Matched using {0} in {1} milliseconds", CudaInvoke.HasCuda ? "GPU" : "CPU", matchTime));
ib_output.Image = result;
label7.Text = String.Format("Matched using {0} in {1} milliseconds", CudaInvoke.HasCuda ? "GPU" : "CPU", matchTime);
}
}
public static void FindMatch(Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography)
{
int k = 2;
double uniquenessThreshold = 0.9;
double hessianThresh = 800;
Stopwatch watch;
homography = null;
modelKeyPoints = new VectorOfKeyPoint();
observedKeyPoints = new VectorOfKeyPoint();
using (UMat uModelImage = modelImage.ToUMat(AccessType.Read))
using (UMat uObservedImage = observedImage.ToUMat(AccessType.Read))
{
SURF surfCPU = new SURF(hessianThresh);
//extract features from the object image
UMat modelDescriptors = new UMat();
surfCPU.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false);
watch = Stopwatch.StartNew();
// extract features from the observed image
UMat observedDescriptors = new UMat();
surfCPU.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false);
//Match the two SURF descriptors
BFMatcher matcher = new BFMatcher(DistanceType.L2);
matcher.Add(modelDescriptors);
matcher.KnnMatch(observedDescriptors, matches, k, null);
mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1);
mask.SetTo(new MCvScalar(255));
Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask);
int nonZeroCount = CvInvoke.CountNonZero(mask);
if (nonZeroCount >= 4)
{
nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints,
matches, mask, 1.5, 20);
if (nonZeroCount >= 4)
homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints,
observedKeyPoints, matches, mask, 2);
}
watch.Stop();
}
matchTime = watch.ElapsedMilliseconds;
}
我真的觉得我离解决方案不远了..希望有人能帮助我
从 Features2DToolbox.GetHomographyMatrixFromMatchedFeatures
退出时,mask
矩阵 is updated to have zeros 其中匹配是异常值(即,在计算的单应性下不对应)。因此,在 mask
上再次调用 CountNonZero
应该会给出匹配质量的指示。
我看到您想要将匹配项分类为 "good" 或 "bad" 而不是仅仅将多个匹配项与单个图像进行比较;从您问题中的示例来看,合理的阈值可能是输入图像中找到的关键点的 1/4。你可能也想要一个绝对最小值,因为如果没有一定数量的证据,你就不能真正认为某件事是好的匹配。因此,例如
bool FindMatch(...) {
bool goodMatch = false;
// ...
homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(...);
int nInliers = CvInvoke.CountNonZero(mask);
goodMatch = nInliers >= 10 && nInliers >= observedKeyPoints.size()/4;
// ...
return goodMatch;
}
在没有达到计算 homography
的分支上,当然 goodMatch
只是在初始化时保持 false。数字 10 和 1/4 有点随意,将取决于您的应用程序。
(警告:以上内容完全来自阅读文档;我还没有真正尝试过。)
我一直在尝试使用 EMGU Example SURFFeature 来确定图像是否在图像集合中。但是我在理解如何确定是否找到匹配项时遇到了问题。
.........原图......................Scene_1(匹配)......................Scene_2(不匹配)
我一直在查看文档并花了数小时寻找可能的解决方案,以了解如何确定图像是否相同。 正如您在下面的图片中看到的,两者都找到了匹配项。
很明显,我要查找的匹配项(连接线)更多,但我如何在代码中检查这一点?
问:如何筛选出好的匹配项?
我的目标是能够将输入图像(从网络摄像头捕获)与数据库中的图像集合进行比较。但在我可以将所有图像保存到数据库之前,我需要知道我可以将输入与哪些值进行比较。 (例如将对象关键点保存在数据库中)
这是我的示例代码(匹配部分):
private void match_test()
{
long matchTime;
using (Mat modelImage = CvInvoke.Imread(@"images\input.jpg", LoadImageType.Grayscale))
using (Mat observedImage = CvInvoke.Imread(@"images.jpg", LoadImageType.Grayscale))
{
Mat result = DrawMatches.Draw(modelImage, observedImage, out matchTime);
//ImageViewer.Show(result, String.Format("Matched using {0} in {1} milliseconds", CudaInvoke.HasCuda ? "GPU" : "CPU", matchTime));
ib_output.Image = result;
label7.Text = String.Format("Matched using {0} in {1} milliseconds", CudaInvoke.HasCuda ? "GPU" : "CPU", matchTime);
}
}
public static void FindMatch(Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography)
{
int k = 2;
double uniquenessThreshold = 0.9;
double hessianThresh = 800;
Stopwatch watch;
homography = null;
modelKeyPoints = new VectorOfKeyPoint();
observedKeyPoints = new VectorOfKeyPoint();
using (UMat uModelImage = modelImage.ToUMat(AccessType.Read))
using (UMat uObservedImage = observedImage.ToUMat(AccessType.Read))
{
SURF surfCPU = new SURF(hessianThresh);
//extract features from the object image
UMat modelDescriptors = new UMat();
surfCPU.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false);
watch = Stopwatch.StartNew();
// extract features from the observed image
UMat observedDescriptors = new UMat();
surfCPU.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false);
//Match the two SURF descriptors
BFMatcher matcher = new BFMatcher(DistanceType.L2);
matcher.Add(modelDescriptors);
matcher.KnnMatch(observedDescriptors, matches, k, null);
mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1);
mask.SetTo(new MCvScalar(255));
Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask);
int nonZeroCount = CvInvoke.CountNonZero(mask);
if (nonZeroCount >= 4)
{
nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints,
matches, mask, 1.5, 20);
if (nonZeroCount >= 4)
homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints,
observedKeyPoints, matches, mask, 2);
}
watch.Stop();
}
matchTime = watch.ElapsedMilliseconds;
}
我真的觉得我离解决方案不远了..希望有人能帮助我
从 Features2DToolbox.GetHomographyMatrixFromMatchedFeatures
退出时,mask
矩阵 is updated to have zeros 其中匹配是异常值(即,在计算的单应性下不对应)。因此,在 mask
上再次调用 CountNonZero
应该会给出匹配质量的指示。
我看到您想要将匹配项分类为 "good" 或 "bad" 而不是仅仅将多个匹配项与单个图像进行比较;从您问题中的示例来看,合理的阈值可能是输入图像中找到的关键点的 1/4。你可能也想要一个绝对最小值,因为如果没有一定数量的证据,你就不能真正认为某件事是好的匹配。因此,例如
bool FindMatch(...) {
bool goodMatch = false;
// ...
homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(...);
int nInliers = CvInvoke.CountNonZero(mask);
goodMatch = nInliers >= 10 && nInliers >= observedKeyPoints.size()/4;
// ...
return goodMatch;
}
在没有达到计算 homography
的分支上,当然 goodMatch
只是在初始化时保持 false。数字 10 和 1/4 有点随意,将取决于您的应用程序。
(警告:以上内容完全来自阅读文档;我还没有真正尝试过。)