EmguCV (OpenCV) ORBDetector 只找到不好的匹配项
EmguCV (OpenCV) ORBDetector finding only bad matches
问题
总的来说,我对计算机视觉还很陌生。我目前正在尝试通过分析 2 张图像来计算单应性。我想使用单应性来校正 1 个图像的透视以匹配另一个。但是我得到的比赛是糟糕的和错误的。所以我做的单应性扭曲完全不对。
当前状态
我正在使用 EmguCV 在 C# 中包装 opencv。
据我所知,我的代码似乎可以工作 "properly"。
我加载我的两个图像并声明一些变量来存储计算工件。
(Image<Bgr, byte> Image, VectorOfKeyPoint Keypoints, Mat Descriptors) imgModel = (new Image<Bgr, byte>(imageFolder + "image0.jpg").Resize(0.2, Emgu.CV.CvEnum.Inter.Area), new VectorOfKeyPoint(), new Mat());
(Image<Bgr, byte> Image, VectorOfKeyPoint Keypoints, Mat Descriptors) imgTest = (new Image<Bgr, byte>(imageFolder + "image1.jpg").Resize(0.2, Emgu.CV.CvEnum.Inter.Area), new VectorOfKeyPoint(), new Mat());
Mat imgKeypointsModel = new Mat();
Mat imgKeypointsTest = new Mat();
Mat imgMatches = new Mat();
Mat imgWarped = new Mat();
VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch();
VectorOfVectorOfDMatch filteredMatches = new VectorOfVectorOfDMatch();
List<MDMatch[]> filteredMatchesList = new List<MDMatch[]>();
请注意,我使用 ValueTuple<Image,VectorOfKeyPoint,Mat>
直接存储图像及其各自的关键点和描述符。
之后是使用ORB检测器和BruteForce匹配器来检测、描述和匹配关键点:
ORBDetector detector = new ORBDetector();
BFMatcher matcher = new BFMatcher(DistanceType.Hamming2);
detector.DetectAndCompute(imgModel.Image, null, imgModel.Keypoints, imgModel.Descriptors, false);
detector.DetectAndCompute(imgTest.Image, null, imgTest.Keypoints, imgTest.Descriptors, false);
matcher.Add(imgTest.Descriptors);
matcher.KnnMatch(imgModel.Descriptors, matches, k: 2, mask: null);
在此之后,我应用 并使用匹配距离阈值进行进一步过滤。
MDMatch[][] matchesArray = matches.ToArrayOfArray();
//Apply ratio test
for (int i = 0; i < matchesArray.Length; i++)
{
MDMatch first = matchesArray[i][0];
float dist1 = matchesArray[i][0].Distance;
float dist2 = matchesArray[i][1].Distance;
if (dist1 < ms_MIN_RATIO * dist2)
{
filteredMatchesList.Add(matchesArray[i]);
}
}
//Filter by threshold
MDMatch[][] defCopy = new MDMatch[filteredMatchesList.Count][];
filteredMatchesList.CopyTo(defCopy);
filteredMatchesList = new List<MDMatch[]>();
foreach (var item in defCopy)
{
if (item[0].Distance < ms_MAX_DIST)
{
filteredMatchesList.Add(item);
}
}
filteredMatches = new VectorOfVectorOfDMatch(filteredMatchesList.ToArray());
禁用这些过滤方法中的任何一个并不会真正使我的结果变得更好或更糟(只是保留所有匹配项),但它们似乎很有意义,所以我保留了它们。
最后,我根据找到的和过滤的匹配计算我的单应性,然后用这个单应性扭曲图像并绘制一些调试图像:
Mat homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(imgModel.Keypoints, imgTest.Keypoints, filteredMatches, null, 10);
CvInvoke.WarpPerspective(imgTest.Image, imgWarped, homography, imgTest.Image.Size);
Features2DToolbox.DrawKeypoints(imgModel.Image, imgModel.Keypoints, imgKeypointsModel, new Bgr(0, 0, 255));
Features2DToolbox.DrawKeypoints(imgTest.Image, imgTest.Keypoints, imgKeypointsTest, new Bgr(0, 0, 255));
Features2DToolbox.DrawMatches(imgModel.Image, imgModel.Keypoints, imgTest.Image, imgTest.Keypoints, filteredMatches, imgMatches, new MCvScalar(0, 255, 0), new MCvScalar(0, 0, 255));
//Task.Factory.StartNew(() => ImageViewer.Show(imgKeypointsModel, "Keypoints Model"));
//Task.Factory.StartNew(() => ImageViewer.Show(imgKeypointsTest, "Keypoints Test"));
Task.Factory.StartNew(() => ImageViewer.Show(imgMatches, "Matches"));
Task.Factory.StartNew(() => ImageViewer.Show(imgWarped, "Warp"));
tl;dr:ORBDetector->BFMatcher->FilterMatches->GetHomography->WarpPerspective
输出
算法示例
测试投影是否出错
匹配时使用交叉检查
原始图像每张为 2448x3264,并按 0.2 缩放在运行对其进行任何计算之前。
问题
基本上它既简单又复杂:我做错了什么?
正如您从上面的示例中看到的那样,我检测特征并匹配它们的方法似乎效果极差。所以我问是否有人可以发现我的代码中的错误。或者就为什么我的结果如此糟糕给出建议,因为互联网上有数百个示例显示它是如何工作的以及它是如何 "easy"。
到目前为止我尝试了什么:
- 输入图像的缩放。如果我将它们缩小很多,我通常会得到更好的结果。
- 检测或多或少的特征。当前使用的默认值为 500。增加或减少这个数字并没有真正使我的结果更好。
- 各种数量的 k 但除了 k = 2 之外的任何其他值对我来说都没有任何意义,因为我不知道如何修改 k > 2 的比率测试。
- 改变过滤器参数,例如使用 0.6-0.9 的比率进行定量测试。
- 使用不同的图片:QR 码、恐龙的轮廓、我放在桌子周围的其他一些随机物品。
- 随着结果的任何变化,重新投影阈值从 1-10 变化
- 正在验证投影本身没有问题。为模型和测试提供相同图像的算法产生单应性并用单应性扭曲图像。图像不应改变。 按预期工作(参见示例图 2)。
- 图 3:匹配时使用交叉检查。看起来更有希望,但仍然不是我所期待的。
- 使用其他距离方法:Hamming、Hamming2、L2Sqr(不支持其他)
我使用的例子:
原始图片:
原始图像可以从这里下载:
https://drive.google.com/open?id=1Nlqv_0sH8t1wiH5PG-ndMxoYhsUbFfkC
提问后的进一步实验
所以我在询问后做了进一步的研究。大多数更改已包含在上面,但我想为这一个单独的部分。
因此,在 运行 陷入如此多的问题并且似乎无处下手之后,我决定 google 提高 original paper on ORB。在此之后,我决定尝试复制他们的一些结果。尝试此操作后,我意识到即使我尝试将匹配图像旋转一定程度进行匹配,匹配看起来还不错,但转换完全失败了。
有没有可能是我尝试复制对象视角的方法是错误的?
MCVE
https://drive.google.com/open?id=17DwFoSmco9UezHkON5prk8OsPalmp2MX
(没有包,但 nuget restore 足以让它编译)
解决方案
问题 1
最大的问题实际上是一个非常简单的问题。我在匹配时不小心翻转了我的模型和测试描述符:
matcher.Add(imgTest.Descriptors);
matcher.KnnMatch(imgModel.Descriptors, matches, 1, null);
但是如果您查看这些函数的文档,您会发现您必须添加模型并与测试图像进行匹配。
matcher.Add(imgModel.Descriptors);
matcher.KnnMatch(imgTest.Descriptors, matches, 1, null);
问题 2
我现在不知道为什么,但 Features2DToolbox.GetHomographyMatrixFromMatchedFeatures
似乎被打破了,我的单应性总是错误的,以一种奇怪的方式扭曲图像(类似于上面的例子)。
为了解决这个问题,我直接使用了 OpenCV 的包装器调用 FindHomography(srcPoints, destPoints, method)
。为了能够做到这一点,我必须编写一个小助手来以正确的格式获取我的数据结构:
public static Mat GetHomography(VectorOfKeyPoint keypointsModel, VectorOfKeyPoint keypointsTest, List<MDMatch[]> matches)
{
MKeyPoint[] kptsModel = keypointsModel.ToArray();
MKeyPoint[] kptsTest = keypointsTest.ToArray();
PointF[] srcPoints = new PointF[matches.Count];
PointF[] destPoints = new PointF[matches.Count];
for (int i = 0; i < matches.Count; i++)
{
srcPoints[i] = kptsModel[matches[i][0].TrainIdx].Point;
destPoints[i] = kptsTest[matches[i][0].QueryIdx].Point;
}
Mat homography = CvInvoke.FindHomography(srcPoints, destPoints, Emgu.CV.CvEnum.HomographyMethod.Ransac);
//PrintMatrix(homography);
return homography;
}
结果
现在一切正常,符合预期:
我遇到了同样的问题并找到了合适的解决方案:github Emgu.CV.Example DrawMatches.cs 一切正常。
我修改了代码和方法FindMatch
看起来像这样:
public static void FindMatch(Mat modelImage, Mat observedImage, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography)
{
int k = 2;
double uniquenessThreshold = 0.80;
homography = null;
modelKeyPoints = new VectorOfKeyPoint();
observedKeyPoints = new VectorOfKeyPoint();
using (UMat uModelImage = modelImage.GetUMat(AccessType.Read))
using (UMat uObservedImage = observedImage.GetUMat(AccessType.Read))
{
var featureDetector = new ORBDetector(9000);
Mat modelDescriptors = new Mat();
featureDetector.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false);
Mat observedDescriptors = new Mat();
featureDetector.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false);
using (var matcher = new BFMatcher(DistanceType.Hamming, false))
{
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);
}
}
}
}
使用:
var model = new Mat(@"image0.jpg");
var scene = new Mat(@"image1.jpg");
Mat result = new Mat();
VectorOfKeyPoint modelKeyPoints;
VectorOfKeyPoint observedKeyPoints;
var matches = new VectorOfVectorOfDMatch();
Mat mask;
Mat homography;
FindMatch(model, scene, out modelKeyPoints, out observedKeyPoints, matches, out mask, out homography);
CvInvoke.WarpPerspective(scene, result, homography, model.Size, Inter.Linear, Warp.InverseMap);
结果:
如果你想观看过程使用下一个代码:
public static Mat Draw(Mat modelImage, Mat observedImage)
{
Mat homography;
VectorOfKeyPoint modelKeyPoints;
VectorOfKeyPoint observedKeyPoints;
using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch())
{
Mat mask;
FindMatch(modelImage, observedImage, out modelKeyPoints, out observedKeyPoints, matches, out mask, out homography);
Mat result = new Mat();
Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints,
matches, result, new MCvScalar(255, 0, 0), new MCvScalar(0, 0, 255), mask);
if (homography != null)
{
var imgWarped = new Mat();
CvInvoke.WarpPerspective(observedImage, imgWarped, homography, modelImage.Size, Inter.Linear, Warp.InverseMap);
Rectangle rect = new Rectangle(Point.Empty, modelImage.Size);
var pts = new PointF[]
{
new PointF(rect.Left, rect.Bottom),
new PointF(rect.Right, rect.Bottom),
new PointF(rect.Right, rect.Top),
new PointF(rect.Left, rect.Top)
};
pts = CvInvoke.PerspectiveTransform(pts, homography);
var points = new Point[pts.Length];
for (int i = 0; i < points.Length; i++)
points[i] = Point.Round(pts[i]);
using (var vp = new VectorOfPoint(points))
{
CvInvoke.Polylines(result, vp, true, new MCvScalar(255, 0, 0, 255), 5);
}
}
return result;
}
}
使用:
var model = new Mat(@"image0.jpg");
var scene = new Mat(@"image1.jpg");
var result = Draw(model, scene);
结果:
问题
总的来说,我对计算机视觉还很陌生。我目前正在尝试通过分析 2 张图像来计算单应性。我想使用单应性来校正 1 个图像的透视以匹配另一个。但是我得到的比赛是糟糕的和错误的。所以我做的单应性扭曲完全不对。
当前状态
我正在使用 EmguCV 在 C# 中包装 opencv。 据我所知,我的代码似乎可以工作 "properly"。
我加载我的两个图像并声明一些变量来存储计算工件。
(Image<Bgr, byte> Image, VectorOfKeyPoint Keypoints, Mat Descriptors) imgModel = (new Image<Bgr, byte>(imageFolder + "image0.jpg").Resize(0.2, Emgu.CV.CvEnum.Inter.Area), new VectorOfKeyPoint(), new Mat());
(Image<Bgr, byte> Image, VectorOfKeyPoint Keypoints, Mat Descriptors) imgTest = (new Image<Bgr, byte>(imageFolder + "image1.jpg").Resize(0.2, Emgu.CV.CvEnum.Inter.Area), new VectorOfKeyPoint(), new Mat());
Mat imgKeypointsModel = new Mat();
Mat imgKeypointsTest = new Mat();
Mat imgMatches = new Mat();
Mat imgWarped = new Mat();
VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch();
VectorOfVectorOfDMatch filteredMatches = new VectorOfVectorOfDMatch();
List<MDMatch[]> filteredMatchesList = new List<MDMatch[]>();
请注意,我使用 ValueTuple<Image,VectorOfKeyPoint,Mat>
直接存储图像及其各自的关键点和描述符。
之后是使用ORB检测器和BruteForce匹配器来检测、描述和匹配关键点:
ORBDetector detector = new ORBDetector();
BFMatcher matcher = new BFMatcher(DistanceType.Hamming2);
detector.DetectAndCompute(imgModel.Image, null, imgModel.Keypoints, imgModel.Descriptors, false);
detector.DetectAndCompute(imgTest.Image, null, imgTest.Keypoints, imgTest.Descriptors, false);
matcher.Add(imgTest.Descriptors);
matcher.KnnMatch(imgModel.Descriptors, matches, k: 2, mask: null);
在此之后,我应用
MDMatch[][] matchesArray = matches.ToArrayOfArray();
//Apply ratio test
for (int i = 0; i < matchesArray.Length; i++)
{
MDMatch first = matchesArray[i][0];
float dist1 = matchesArray[i][0].Distance;
float dist2 = matchesArray[i][1].Distance;
if (dist1 < ms_MIN_RATIO * dist2)
{
filteredMatchesList.Add(matchesArray[i]);
}
}
//Filter by threshold
MDMatch[][] defCopy = new MDMatch[filteredMatchesList.Count][];
filteredMatchesList.CopyTo(defCopy);
filteredMatchesList = new List<MDMatch[]>();
foreach (var item in defCopy)
{
if (item[0].Distance < ms_MAX_DIST)
{
filteredMatchesList.Add(item);
}
}
filteredMatches = new VectorOfVectorOfDMatch(filteredMatchesList.ToArray());
禁用这些过滤方法中的任何一个并不会真正使我的结果变得更好或更糟(只是保留所有匹配项),但它们似乎很有意义,所以我保留了它们。
最后,我根据找到的和过滤的匹配计算我的单应性,然后用这个单应性扭曲图像并绘制一些调试图像:
Mat homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(imgModel.Keypoints, imgTest.Keypoints, filteredMatches, null, 10);
CvInvoke.WarpPerspective(imgTest.Image, imgWarped, homography, imgTest.Image.Size);
Features2DToolbox.DrawKeypoints(imgModel.Image, imgModel.Keypoints, imgKeypointsModel, new Bgr(0, 0, 255));
Features2DToolbox.DrawKeypoints(imgTest.Image, imgTest.Keypoints, imgKeypointsTest, new Bgr(0, 0, 255));
Features2DToolbox.DrawMatches(imgModel.Image, imgModel.Keypoints, imgTest.Image, imgTest.Keypoints, filteredMatches, imgMatches, new MCvScalar(0, 255, 0), new MCvScalar(0, 0, 255));
//Task.Factory.StartNew(() => ImageViewer.Show(imgKeypointsModel, "Keypoints Model"));
//Task.Factory.StartNew(() => ImageViewer.Show(imgKeypointsTest, "Keypoints Test"));
Task.Factory.StartNew(() => ImageViewer.Show(imgMatches, "Matches"));
Task.Factory.StartNew(() => ImageViewer.Show(imgWarped, "Warp"));
tl;dr:ORBDetector->BFMatcher->FilterMatches->GetHomography->WarpPerspective
输出
原始图像每张为 2448x3264,并按 0.2 缩放在运行对其进行任何计算之前。
问题
基本上它既简单又复杂:我做错了什么? 正如您从上面的示例中看到的那样,我检测特征并匹配它们的方法似乎效果极差。所以我问是否有人可以发现我的代码中的错误。或者就为什么我的结果如此糟糕给出建议,因为互联网上有数百个示例显示它是如何工作的以及它是如何 "easy"。
到目前为止我尝试了什么:
- 输入图像的缩放。如果我将它们缩小很多,我通常会得到更好的结果。
- 检测或多或少的特征。当前使用的默认值为 500。增加或减少这个数字并没有真正使我的结果更好。
- 各种数量的 k 但除了 k = 2 之外的任何其他值对我来说都没有任何意义,因为我不知道如何修改 k > 2 的比率测试。
- 改变过滤器参数,例如使用 0.6-0.9 的比率进行定量测试。
- 使用不同的图片:QR 码、恐龙的轮廓、我放在桌子周围的其他一些随机物品。
- 随着结果的任何变化,重新投影阈值从 1-10 变化
- 正在验证投影本身没有问题。为模型和测试提供相同图像的算法产生单应性并用单应性扭曲图像。图像不应改变。 按预期工作(参见示例图 2)。
- 图 3:匹配时使用交叉检查。看起来更有希望,但仍然不是我所期待的。
- 使用其他距离方法:Hamming、Hamming2、L2Sqr(不支持其他)
我使用的例子:
原始图片: 原始图像可以从这里下载: https://drive.google.com/open?id=1Nlqv_0sH8t1wiH5PG-ndMxoYhsUbFfkC
提问后的进一步实验
所以我在询问后做了进一步的研究。大多数更改已包含在上面,但我想为这一个单独的部分。
因此,在 运行 陷入如此多的问题并且似乎无处下手之后,我决定 google 提高 original paper on ORB。在此之后,我决定尝试复制他们的一些结果。尝试此操作后,我意识到即使我尝试将匹配图像旋转一定程度进行匹配,匹配看起来还不错,但转换完全失败了。
有没有可能是我尝试复制对象视角的方法是错误的?
MCVE
https://drive.google.com/open?id=17DwFoSmco9UezHkON5prk8OsPalmp2MX (没有包,但 nuget restore 足以让它编译)
解决方案
问题 1
最大的问题实际上是一个非常简单的问题。我在匹配时不小心翻转了我的模型和测试描述符:
matcher.Add(imgTest.Descriptors);
matcher.KnnMatch(imgModel.Descriptors, matches, 1, null);
但是如果您查看这些函数的文档,您会发现您必须添加模型并与测试图像进行匹配。
matcher.Add(imgModel.Descriptors);
matcher.KnnMatch(imgTest.Descriptors, matches, 1, null);
问题 2
我现在不知道为什么,但 Features2DToolbox.GetHomographyMatrixFromMatchedFeatures
似乎被打破了,我的单应性总是错误的,以一种奇怪的方式扭曲图像(类似于上面的例子)。
为了解决这个问题,我直接使用了 OpenCV 的包装器调用 FindHomography(srcPoints, destPoints, method)
。为了能够做到这一点,我必须编写一个小助手来以正确的格式获取我的数据结构:
public static Mat GetHomography(VectorOfKeyPoint keypointsModel, VectorOfKeyPoint keypointsTest, List<MDMatch[]> matches)
{
MKeyPoint[] kptsModel = keypointsModel.ToArray();
MKeyPoint[] kptsTest = keypointsTest.ToArray();
PointF[] srcPoints = new PointF[matches.Count];
PointF[] destPoints = new PointF[matches.Count];
for (int i = 0; i < matches.Count; i++)
{
srcPoints[i] = kptsModel[matches[i][0].TrainIdx].Point;
destPoints[i] = kptsTest[matches[i][0].QueryIdx].Point;
}
Mat homography = CvInvoke.FindHomography(srcPoints, destPoints, Emgu.CV.CvEnum.HomographyMethod.Ransac);
//PrintMatrix(homography);
return homography;
}
结果
现在一切正常,符合预期:
我遇到了同样的问题并找到了合适的解决方案:github Emgu.CV.Example DrawMatches.cs 一切正常。
我修改了代码和方法FindMatch
看起来像这样:
public static void FindMatch(Mat modelImage, Mat observedImage, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography)
{
int k = 2;
double uniquenessThreshold = 0.80;
homography = null;
modelKeyPoints = new VectorOfKeyPoint();
observedKeyPoints = new VectorOfKeyPoint();
using (UMat uModelImage = modelImage.GetUMat(AccessType.Read))
using (UMat uObservedImage = observedImage.GetUMat(AccessType.Read))
{
var featureDetector = new ORBDetector(9000);
Mat modelDescriptors = new Mat();
featureDetector.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false);
Mat observedDescriptors = new Mat();
featureDetector.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false);
using (var matcher = new BFMatcher(DistanceType.Hamming, false))
{
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);
}
}
}
}
使用:
var model = new Mat(@"image0.jpg");
var scene = new Mat(@"image1.jpg");
Mat result = new Mat();
VectorOfKeyPoint modelKeyPoints;
VectorOfKeyPoint observedKeyPoints;
var matches = new VectorOfVectorOfDMatch();
Mat mask;
Mat homography;
FindMatch(model, scene, out modelKeyPoints, out observedKeyPoints, matches, out mask, out homography);
CvInvoke.WarpPerspective(scene, result, homography, model.Size, Inter.Linear, Warp.InverseMap);
结果:
如果你想观看过程使用下一个代码:
public static Mat Draw(Mat modelImage, Mat observedImage)
{
Mat homography;
VectorOfKeyPoint modelKeyPoints;
VectorOfKeyPoint observedKeyPoints;
using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch())
{
Mat mask;
FindMatch(modelImage, observedImage, out modelKeyPoints, out observedKeyPoints, matches, out mask, out homography);
Mat result = new Mat();
Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints,
matches, result, new MCvScalar(255, 0, 0), new MCvScalar(0, 0, 255), mask);
if (homography != null)
{
var imgWarped = new Mat();
CvInvoke.WarpPerspective(observedImage, imgWarped, homography, modelImage.Size, Inter.Linear, Warp.InverseMap);
Rectangle rect = new Rectangle(Point.Empty, modelImage.Size);
var pts = new PointF[]
{
new PointF(rect.Left, rect.Bottom),
new PointF(rect.Right, rect.Bottom),
new PointF(rect.Right, rect.Top),
new PointF(rect.Left, rect.Top)
};
pts = CvInvoke.PerspectiveTransform(pts, homography);
var points = new Point[pts.Length];
for (int i = 0; i < points.Length; i++)
points[i] = Point.Round(pts[i]);
using (var vp = new VectorOfPoint(points))
{
CvInvoke.Polylines(result, vp, true, new MCvScalar(255, 0, 0, 255), 5);
}
}
return result;
}
}
使用:
var model = new Mat(@"image0.jpg");
var scene = new Mat(@"image1.jpg");
var result = Draw(model, scene);
结果: