拍建筑的时候,竖线歪一点,整张照片就散了。建筑相机要解决的问题只有一句话: 找到画面里的建筑直线,按相机真实的朝向重新投影。
下面是它在每一步实际做的事。
一、不是把楼扶正,是还原真实朝向
大多数「自动扶正」会把画面压成平行投影,楼是正了,但仰头看天的压迫感和往深处延伸的纵深全没了。 建筑相机做的是另一件事:恢复相机当时的真实姿态,再按这个姿态重投影。 楼自然会正,因为建筑本来就是竖的;而纵深也一并留了下来。
二、用重力定义「世界上竖直」
一切从加速度计开始。陀螺仪会漂移,重力方向不会 —— 手机静止时它指的就是铅垂线。 把重力向量归一化后构造一个旋转矩阵,相机坐标系(x 向右、y 向下、z 向前)里就有了确定的「世界竖直」。
如果手机接近朝天或朝地,重力在画面上的投影太短,就没法定义水平参考了。 这时应用直接提示「请调整机位」,而不是给一个歪的结果。
三、找到竖直消失点
平行于世界竖直方向的建筑线,在照片里并不平行 —— 它们收敛到同一点。 这个点就是竖直消失点,知道它和焦距,就能量出相机相对建筑的姿态。
检测用 OpenCV 的 LSD 而不是霍夫变换:我们需要有明确端点的线段,也更容易判断它延伸多远。
拟合用齐次坐标下的加权最小二乘,竖直消失点写作 [vx, 1, vz] ——
中间固定为 1,是为了同时表示「消失点在无穷远」的情况(正对建筑拍、竖线完全平行时)。
拟合之后还有一排门槛:内点权重要占 45% 以上;内点在画面上的水平跨度要超过画面宽度的 8%; 平均残差要够小;消失点要落在合理视场内。任意一条不满足,这一帧就判定为「没有可用观测」。
四、水平方向:曼哈顿约束
建筑摄影几乎总是拍互相垂直的两组方向。这个性质很强,强到可以当约束用:
水平消失点一定在竖直消失点的正交方向上。所以不直接找它,而是在法平面里搜一个偏航角,
扫 [-44°, +44°],看哪个角度能让最多线段对齐。
五、严格裁切:宁可少拍,不裁掉建筑
做了透视矫正,画面边缘就可能落到有效视场之外。常见做法是把四边往里缩,但那只保证「大概在框里」。 建筑相机求的是一个尽可能大、且完整落在有效投影内的矩形。
代价是拍不到原本在画面边缘的内容。这是有意的取舍:宁可少拍,也不给一张缺了屋檐的照片。 如果连画面宽度的六分之一都放不下,拍照按钮会直接禁用。
六、三种模式
一点:只有一组主要方向时。矫正横滚、俯仰和主方向朝向,纵深汇聚保留。
两点:能判断出两组线段时。矫正横滚与俯仰,横向汇聚保留,适合有明确转角的场景。
三点:不矫正,保存原始 JPEG。仰拍常常是有意为之的表达,自动压平反而毁了照片 ——
这个决定权交回给人。
七、时间维度:噪声与主动移动
逐帧独立估计会抖。所以每个参数都走带时间常数的指数平滑,并区分两者: 误差小时用长时间常数(稳),误差大时自动切到短时间常数(跟得上)。判断依据是误差落在 1° 到 4° 之间的什么位置。
消失点还有两道额外保护:单帧异常值要被连续多次相近观测确认才接受;变换速度有上限,不会因一个突变而瞬移。
八、原片永远在
拍照走相机能输出的最大 JPEG,原始字节与 EXIF 原样保留;矫正结果另行写入相册的
Archicamera 目录。两者互不覆盖 —— 后期调色、换天空、做合成,都要从原始数据开始。
三点模式则完全跳过解码。
九、还没解决的
自动判断依赖现场:没有足够建筑直线时(纯天空、纯植被、弧形幕墙),只保留竖线矫正,其余靠手动微调。
相机是逐台标定的,还没在所有机型上做过实拍验证;预览用的是快门前的低分辨率矩阵, 曝光期间手机有移动的话,成片可能和预览不完全一致。
原片保存目前依赖大图解码成功,极端内存情况下仍可能丢 —— 正确做法是先独立写入原始字节,再处理矫正。这条记在这里,等着修。