我计算光流量:
Const MAXFEATURES As Integer = 100 imgA = New Image(Of [Structure].Bgr,Byte)("pic1.bmp") imgB = New Image(Of [Structure].Bgr,Byte)("pic2.bmp") grayA = imgA.Convert(Of Gray,Byte)() grayB = imgB.Convert(Of Gray,Byte)() imagesize = cvGetSize(grayA) pyrBufferA = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray,Byte) _ (imagesize.Width + 8,imagesize.Height / 3) pyrBufferB = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray,imagesize.Height / 3) features = MAXFEATURES featuresA = grayA.GoodFeaturesToTrack(features,0.01,25,3) grayA.FindCornerSubPix(featuresA,New System.Drawing.Size(10,10),New System.Drawing.Size(-1,-1),New Emgu.CV.Structure.MCvTermCriteria(20,0.03)) features = featuresA(0).Length Emgu.CV.OpticalFlow.PyrLK(grayA,grayB,pyrBufferA,pyrBufferB,_ featuresA(0),New Size(25,25),3,_ New Emgu.CV.Structure.MCvTermCriteria(20,0.03D),flags,featuresB(0),status,errors) pointsA = New Matrix(Of Single)(features,2) pointsB = New Matrix(Of Single)(features,2) For i As Integer = 0 To features - 1 pointsA(i,0) = featuresA(0)(i).X pointsA(i,1) = featuresA(0)(i).Y pointsB(i,0) = featuresB(0)(i).X pointsB(i,1) = featuresB(0)(i).Y Next Dim Homography As New Matrix(Of Double)(3,3) cvFindHomography(pointsA.Ptr,pointsB.Ptr,Homography,HOMOGRAPHY_METHOD.RANSAC,1,0)
它看起来正确,相机向左和向上移动:
现在我想知道相机移动和旋转了多少.如果我宣布我的相机位置及其所看到的内容:
' Create camera location at origin and lookat (straight ahead,1 in the Z axis) Location = New Matrix(Of Double)(2,3) location(0,0) = 0 ' X location location(0,1) = 0 ' Y location location(0,2) = 0 ' Z location location(1,0) = 0 ' X lookat location(1,1) = 0 ' Y lookat location(1,2) = 1 ' Z lookat
如何计算新位置和外观?
如果我这样做是错的或者有更好的方法,那么任何建议都会非常受欢迎,谢谢!
简答
基本上它不能用一台摄像机完成.但它可以用两个相机完成.
冗长的答案(我想更深入地解释,没有双关语意)
我会试着解释一下,说我们在图像中选择两个点并向左移动相机.我们知道每个点B1的相机距离为20mm,B2点为40mm.现在让我们假设我们处理图像,我们的测量结果是A1是(0,2)而A2是(0,4)它们分别与B1和B2有关.现在A1和A2不是测量值;它们是运动的像素.
我们现在要做的是将A1和A2的变化乘以计算的常数,该常数将是B1和B2的实际世界距离.注意:根据测量B *,每个都不同.这一切都涉及Angle of view或更多通常称为不同距离摄影的视野.如果您知道相机CCD上每个像素的大小和相机内部镜头的f数,则可以精确计算常数.
我希望情况并非如此,所以在不同的距离你必须放置一个你知道长度的物体,看看它占用了多少像素.关闭你可以使用标尺使事情变得更容易.通过这些测量.您获取此数据并形成一条最佳拟合线的曲线.如果X轴是物体的距离,Y轴将是像素与距离比的常数,你必须乘以你的运动.
那么我们如何应用这条曲线.嗯,这是猜测的工作.理论上,运动A *的测量越大,物体越接近相机.在我们的例子中,我们的A1的比率> A2分别表示5mm和3mm,我们现在知道B1点移动了10mm(2x5mm),B2移动了6mm(2x6mm).但是让我们面对它 – 我们永远不会知道B,我们永远无法分辨移动的距离是否是一个物体的20个像素,近距离没有移动很远,或者一个物体远远移动了很远的距离.这就是为什么像XBox Kinect这样的东西使用额外的传感器来获取可以绑定到图像中的对象的深度信息.
您可以尝试使用两台摄像机尝试这些摄像机,因为已知这些摄像机之间的距离可以更精确地计算运动(有效地不使用深度传感器).这背后的数学是非常复杂的,我建议查阅一些关于这个主题的期刊论文.如果你想让我解释这个理论,我可以尝试.
我的所有经验来自为我的PHD设计高速视频采集和图像处理所以相信我,不能用一台相机完成,对不起.我希望其中一些有所帮助.
干杯
克里斯
[编辑]
因为它是Kinect,我会假设你有一些与每个点相关的深度信息,否则你需要弄清楚如何得到它.
您需要开始使用的等式是视场(FOV):
o / d = i / f
哪里:
f等于镜头的焦距,通常以mm为单位(即18 28 30 50为标准示例)
d是从kinect数据收集的镜头的物距
o是物体尺寸(或垂直于光轴并由光轴平分的“视场”).
i是图像尺寸(或垂直于光轴并由光轴对分的“场光阑”).
我们需要计算i,其中o是我们未知的因此对于i(这是一个对角线测量),
我们将需要ccd上像素的大小,这将以微米或μm为单位,您将需要找到这些信息,因为我们知道我们将其视为14um,这是中档区域扫描相机的标准.
所以首先我们需要计算出水平尺寸(ih),它是相机宽度的像素数量乘以ccd像素的尺寸(我们将使用640 x 320)
所以:ih = 640 * 14um = 8960um
= 8960/1000 = 8.96mm
现在我们需要垂直尺寸(iv)相同的过程但高度
所以:iv =(320 * 14um)/ 1000 = 4.48mm
现在我发现毕达哥拉斯定理毕达哥拉斯定理a ^ 2 b ^ 2 = c ^ 2
所以:i = sqrt(ih ^ 2 _ iv ^ 2)
= 10.02 mm
现在我们假设我们有一个28毫米镜头.同样,必须找到这个确切的值.所以我们的等式重新排列,给我们o是:
o =(i * d)/ f
记住o将是对角线(我们假设物体或点距离是50mm):
o =(10.02mm * 50mm)/ 28mm
17.89mm
现在我们需要计算水平尺寸(哦)和垂直尺寸(ov),因为这将给出物体移动的每个像素的距离.现在,当FOVαCCD或i与o成正比时,我们将计算出比率k
k = i / o
= 10.02 / 17.89 = 0.56
所以:
o水平尺寸(哦):
哦= ih / k
= 8.96mm / 0.56 =每像素16mm
o垂直尺寸(ov):
ov = iv / k
= 4.48mm / 0.56 =每像素8mm
现在我们有了我们需要的常量,让我们在一个例子中使用它.如果我们50mm处的物体从位置(0,0)移动到(2,4)那么现实生活中的测量值是:
(2 * 16mm,4 * 8mm)=(32mm,32mm)
毕竟,毕达哥拉斯定理:a ^ 2 b ^ 2 = c ^ 2
总距离= sqrt(32 ^ 2 32 ^ 2)
= 45.25mm
复杂我知道,但是一旦你在一个程序中有这个,它就会更容易.因此,对于每一点,您将不得不重复至少一半的过程,因为d将会改变,因此o对于您的检查的每个点.
希望这能帮到你的路上,
干杯克里斯