如何测算出任一副图片中的物体的实际尺寸?

数学,计算机视觉,图形图像处理

http://www.zhihu.com/question/20448353

从一幅图像中无法测出物体的长度,因为缺乏参照物,但可以测出两个平行物体的长度比例。如果已知一个物体的实际大小(比如在图片中放上一枚1元硬币或者知道某个柜子有多高),那么就可以通过长度比和参照物的已知长度测出物体长度。具体方法见文献[1],因为需要一些矩阵运算和摄像头成像方面的推导,这里只大概说说原理。楼上诸位所述也是这种原理。


图像测量利用了摄像头成像也就是小孔成像的几个性质[2]
第一,摄像头把平行的直线映射为图像上相交直线,笔直的铁轨在远处相交就是这个道理,这个交点被称为消隐点(vanish point)。可以认为平行空间直线在无穷远处相交,消隐点则是这一交点的像。所有水平的平行直线族都各自相交于无穷远处的一点,这些点构成无穷远直线,这条直线在图像上的像叫地平线。我们所居住的三维空间中存在三组相互垂直的直线(例如水平两组,x轴和y轴方向,竖直一组,z轴方向),所有xyz方向上的平行直线在一张图片上会分别相交于各自的一个消隐点。并且水平直线对应的两个消隐点如果连起来,连线就是地平线。测量的关键,就是要得到这些消隐点,因此有很多竖直线(如书架)或水平线(如地板砖)的图片就容易测量。

第二,摄像头把三维空间投影到二维的图像上,保持直线交比不变,交比是四个点两两比例的比例。所以如果在三维空间中的一条直线上有四个点,那么它们映射到图片上的四个点后,这四个点的交比不变。

文献[1]通过这些条件,给出了从图片上计算长度比的公式。通过示意图我们可以更加直观地看出它是如何工作的:


首先,假设我们已知蓝色小人Bob的身高,要求出红色小人John的身高,只需要知道两人的身高比值就可以:


我们用大写字母表示真实的坐标,随后用小写字母表示图片上的像素坐标。两人的身高比值BE/AF可以这么求:首先连接AB,然后过E点做AB的平行线交AF于点D,因为ABED是个矩形,所以要求的比值就等于AD/AF。然而,这种判断是在三维空间中做出的,当物体成像为图片,所有点的位置都会发生变化(不要问我圆头为什么会变成方头)


其中最显著的变化是平行线相交了,由此我们可以找到三个方向的消隐点,这可以通过对竖直和两组水平平行线求延长线获得:


注意我们把水平平行线对应的两个消隐点连接起来,得到了一条在(无穷)远处的直线,每个人都熟悉它,它就是地平线。地平线上所有的点都有一个性质:从其上一个点引出的所有直线都是相互水平平行的。

因此点D在图上的坐标d是这么求出的:
1.
画出地平线
2.
延长ab,交地平线于点c
3.
延长ce,交af,也就是John于点d
因为点c在无穷远处,所以cdca在空间中是平行直线,abed也就是上面说述真实空间中矩形ABED的像。

然而,知道了某些点在图像上的像,它们的实际长度比是无法直接从图上测得的,因为大家的深度不一样,这时就要利用成像前后一条直线上四个点交比不变的性质,考察红色小人John身上的三个点ADF以及其延长到无穷远处的点G,就可以得到(大写字母换成小写字母)
(AD/AF)/(GD/GF)=(ad/af)/(gd/gf)
因为已经求出了点d,等式右边所有的量都可以从图像上测出。等式左边的点G在真实空间是所有垂直直线的交点,这个点在无穷远,和无穷相比点F和点D的差异可以忽略不计,所以GD/GF=1,这样就得到最终结果:
AD/AF = (ad/af)/(gd/gf)

[1] Criminisi A, Reid I, Zisserman A. Single view metrology[J]. InternationalJournal of Computer Vision, 2000, 40(2): 123-148.
[2] Hartley R, Zisserman A. Multiple view geometry in computer vision[M].Cambridge university press, 2003.


PS:
有知友指出的image rectification概念其实是双目视觉中的一个专有概念,假如有两幅图像拍摄的物体相同,但是摄影师站位不同,一左一右,通过某种变换可以对两幅图像分别做一个变换,(近似)让左边这幅图像上每一行的每一个像素点代表的物体上的点在右边那副图像上的像点也恰好在右图的同一行,这种变换过程叫做image rectification。其作用是为了随后计算视差图方便。

在C语言中,处理上下文无关文法(Context-Free Grammar, CFG)并找出所有的导空符号是一个相对复杂的过程,因为它涉及到语法分析算法,比如LR(1)、LL(1)等。这里我会提供一个简单概念性的解释,但实际编写完整的代码需要利用专门的词法分析和语法分析库,如Yacc或ANTLR。 首先,你需要明确上下文无关文法(CFG)的具体形式,通常包括非终结符、终结符、开始符号以及规则。导空符号是指那些不包含其他符号的句子,即最短的句型。 以下是一个简单的示例,假设我们有一个非常基础的文法: ```c typedef enum { Terminal, NonTerminal } SymbolType; // 定义文法符号 struct GrammarSymbol { char name; SymbolType type; }; // 示例文法规则 GrammarSymbol rules[] = { {'S', NonTerminal}, {'A', NonTerminal}, {'B', NonTerminal}, {'a', Terminal}, {'b', Terminal}, {'S -> A a', NULL}, // S由A和'a'组成 {'S -> B b', NULL}, // S也可由B和'b'组成 {'A -> a', NULL}, // A可以简化为'a' {'B -> b', NULL} // B可以简化为'b' }; // 求导空符号函数(仅用于演示,未实现) void findDerivationClosure(GrammarSymbol* grammar) { // 这里需要实现语法分析算法,找到每个非终结符的封闭集合 } int main() { findDerivationClosure(rules); return 0; } ``` 真正的实现会涉及更复杂的分析过程,如构建解析树或使用状态机。然而,在这个简化的例子中,`findDerivationClosure` 函数并未给出,因为这超出了简单的C代码范围。实际应用中,你会需要学习相关的理论知识并使用适当的工具包。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值