如何在EmguCv中使用捕获时创建旋转边界区域
本文关键字:创建 旋转 区域 边界 EmguCv | 更新日期: 2023-09-27 18:16:53
我的问题如下:
使用EmguCv (c# OpenCV),我必须写一个应用程序,可以检测我的数字旋转或不使用我的电脑摄像头。我用Capture从我的网络摄像头捕捉帧。此外,我使用SmoothGausian
和Canny
过滤器"清理"了每一帧。多亏了这一点,相机所能看到的只是我画在纸上的形象。我检查了我的人物的hu1
时刻,而检查轮廓在我的框架,我只选择那些有相似的hu1
时刻。现在是最难的部分了。当我开始旋转纸张时,我想计算旋转的角度。我发现我可以使用边界区域,也就是包围轮廓线的正方形,我可以计算这个区域两点之间的线(以前和现在)的角度。不幸的是,这个边界区域不旋转,现在我问你们的帮助:)有人知道如何解决这个问题:)?
//img - filtrated rame from a camera
var tmp = img.Convert<Gray, byte>().FindContours();
for (; tmp.HNext != null; tmp = tmp.HNext)
{
if(tmp.GetMoments().GetHuMoment().hu1 > 0.325 && tmp.GetMoments().GetHuMoment().hu1 < 0.34)
//if (tmp.GetMoments().GetHuMoment().hu1 > 0.33 && tmp.GetMoments().GetHuMoment().hu1 < 0.335)
{
var color1 = new Bgra(0, 255, 0, 255);
drawImg.Draw(tmp, color1, 2);
int left = tmp.BoundingRectangle.Left;
int top = tmp.BoundingRectangle.Top;
int right = tmp.BoundingRectangle.Right;
Point[] line2 = { new Point(left, top), new Point(right, top) };
drawImg.DrawPolyline(line2, false, new Bgra(255, 0, 0, 255), 1);
plik.WriteLine(left + "'t" + top);
Point[] tab = tmp.ToArray();
Point[] pointy = {tab[0], new Point( (int)tmp.GetMoments().GravityCenter.x, (int)tmp.GetMoments().GravityCenter.y )};
Console.WriteLine(tab[0].ToString());
drawImg.DrawPolyline(pointy, false, new Bgra(0, 0, 255, 255), 2);
}
}
你需要看一下模板匹配和轮廓匹配。OpenCV提供的本地模板匹配不考虑旋转和缩放。
在第一个参考中,你会发现下载的代码和一堆关于如何检测旋转的有用评论。
第二篇是一篇有趣的博客文章,讨论了如何一步一步地进行轮廓匹配(模板匹配旋转不变量的一种情况),并分享了实现这一技巧的源代码。
都是使用OpenCV的C/c++源代码,所以我想你把它们翻译成c#是没有问题的。
要计算参考图和您使用网络摄像头获得的图之间的旋转,我可以建议您:
- 利用emgucv哈里斯角点检测器 提取参考图像的角点集合(xi)
- 提取角集(yi)仍然使用emgucv harris角检测器
- 计算xi和yi之间的匹配使用一个简单的匹配策略,如ZNCC
- 在步骤3计算的噪声匹配之间计算相似变换矩阵T
前三个步骤非常简单,你可以在google上找到代码示例(搜索opencv或emgucv harris角检测器)。
我将给你一些有用的代码从我的论文中提取的步骤4,假设你的对象之间具有各向同性缩放的相似变换:
/// <summary>
/// Compute the similarity transformation between a set of noise correspondance matching pairs.
/// A similarity transformation has got 5 degrees of freedom:
/// - tx and ty for translation
/// - isotropic scaling s = Math.Sqrt (a^2 + b ^ 2)
/// - orientation = tan^-1 (b'a).
///
///
/// Similarity Matrix Transformation
///
/// | x' | | a -b tx | | x |
/// | y' | = | a b ty | . | y |
/// | 1 | | 0 0 1 | | 1 |
///
/// </summary>
/// <param name="matches">Putative Correspondance Pairs</param>
/// <param name="homographyDirection">Direction of Transformation Estimation</param>
/// <returns>Homography Matrix shaped as a Similarity Transformation</returns>
public static HomographyMatrix GetSimilarityHomographyMatrixLeastSquares(MatchedImageFeature[] matches)
{
int n = matches.Length;
Matrix<float> M = new Matrix<float>(2, 3);
PointF[] srcPoints = new PointF[n];
PointF[] dstPoints = new PointF[n];
for (int i = 0; i < n; i++)
{
srcPoints[i] = matches[i].ObservedFeature.KeyPoint.Point;
dstPoints[i] = matches[i].SimilarFeatures[0].Feature.KeyPoint.Point;
}
GCHandle handleSrcPts = GCHandle.Alloc(srcPoints, GCHandleType.Pinned);
Matrix<float> srcMatrix = new Matrix<float>(n, 1, 2, handleSrcPts.AddrOfPinnedObject(), 2 * sizeof(float));
GCHandle handleDstPts = GCHandle.Alloc(dstPoints, GCHandleType.Pinned);
Matrix<float> dstMatrix = new Matrix<float>(n, 1, 2, handleDstPts.AddrOfPinnedObject(), 2 * sizeof(float));
cvEstimateRigidTransform(srcMatrix, dstMatrix, M, 0);
handleDstPts.Free();
handleSrcPts.Free();
double xScale, yScale;
xScale = yScale= Math.Sqrt(Math.Pow(M[0,0],2) + Math.Pow(M[0,1],2));
double xOffset = M[0, 2];
double yOffset = M[1, 2];
double theta = Math.Atan(M[0, 1] / M[0, 0]) * (180 / Math.PI);
HomographyMatrix similarityTransform = new HomographyMatrix();
similarityTransform[0, 0] = M[0, 0];
similarityTransform[0, 1] = M[0, 1];
similarityTransform[0, 2] = M[0, 2];
similarityTransform[1, 0] = M[1, 0];
similarityTransform[1, 1] = M[1, 1];
similarityTransform[1, 2] = M[1, 2];
similarityTransform[2, 0] = 0;
similarityTransform[2, 1] = 0;
similarityTransform[2, 2] = 1;
return similarityTransform;
}