ImageMagick 示例 -
镜头校正

索引
ImageMagick 示例前言及索引
镜头校正简介
非缩放约束
预制参数集
从头开始校准
示例
键盘示例 (由 El-Supremo 提供)
 
校正镜头畸变 (PDF)
拍摄照片时,生成的图像实际上会因镜头效应和球面透视效应而发生畸变。如果您打算使用照片,通常需要校正这些效应,本节将对此进行探讨。本页的大部分内容由 Wolfgang Hugemann 贡献。

镜头校正简介

鱼眼镜头和低成本广角镜头(或者更确切地说,当设置为短焦距时变焦镜头)通常会产生明显的桶形畸变。但是,可以通过对数字照片应用适当的算法变换来纠正这种畸变。Panorama Tools 引入并由 PTlens 使用的最常用的镜头校正算法之一,也由 ImageMagick 提供,称为 桶形校正畸变方法。在这种解决问题的方法中,畸变由四个变换参数 a, b, c, d 控制,这些参数必须选择得当,以纠正特定镜头(或者更确切地说,当设置为特定焦距时变焦相机)产生的畸变。这些参数的合适值很难通过试错法找到。在下面,我们将介绍如何使用 Hugin 有效地确定此模型的镜头校正参数。Hugin 是一个用于 Panorama Tools 的免费图形用户界面,可用于各种操作系统。如果您不想处理镜头校正的细节,可以跳过本页的其余部分,直接购买 PTlens,它为大量数码相机和镜头提供了复杂的镜头校正功能,而且价格合理(通过使用其庞大的镜头数据库)。如今,一些数码相机(如尼康 P7000)甚至在其内部图像处理步骤中集成了镜头校正。对于使用不提供此功能的相机拍摄的照片,ImageMagick 使您能够将镜头校正作为更大图像处理脚本的一部分。以下文字是论文 校正镜头畸变 (PDF)(处理事故重建中的应用)的节选。这里给出的解释更注重实际操作,重点介绍如何获取适当的镜头校正参数。

非缩放约束

桶形畸变 所述,桶形畸变由以下数学公式定义
  R = ( a * r^3  +  b * r^2  +  c * r  +  d ) * r
其中 r 是到数字照片几何图像中心的距离,R 是原始图像中的等效半径。与所有这种映射一样,上述等式定义了一种“颜色查找函数”,即在半径 r 处查找像素颜色的位置。半径 rR 通过较小图像尺寸(即通常是图像的高度)的一半进行归一化,这样 r = R = 1 表示图像上边和下边中点的半径。在校正数字照片时,我们应该注意非缩放约束
  a + b + c + d = 1
这显然在 r = 1 时给出 R = 1。Panorama Tools 通过其他参数计算参数 d
  d = 1 - a - b - c
使我们有三个自由模型参数,因此参数 d 通常被省略。如果省略,ImageMagick 会自动通过非缩放约束来计算 d。因此,镜头校正的典型 ImageMagick 命令行如下所示
  magick input.jpg -distort barrel '0.06335 -0.18432 -0.13008' output.jpg
d 的计算留给 ImageMagick。我们这里提到的 Panorama Tools 的镜头校正方法假设镜头的光轴和图像中心是相同的,在实际情况中(由于制造公差)并非严格如此。此外,它忽略了 胡须畸变 等效应。尽管如此,它在实践中似乎工作得惊人地精确。 [Graph]如曲线所示(a = 0.05, b = -0.25, c = 0.05),这种关系通常用于 0 到 1.5 的范围内(纵横比 3:2),穿过点 (0,0) 和 (1,1),并且对于 r > 1 必须递减。

预制参数集

PTlens 当前的镜头数据库是该程序的“核心”,它被加密,只能由 PTlens 本身读取。但是,直到 2006 年 2 月,PTlens 的数据库都是用 XML 格式编码的,即一种易于编辑的文本格式。PTlens 的 XML 数据库的这个 2006 版本仍然(合法地)在 Hugin 的 SourceForge 网站 上提供,并为许多旧相机型号提供数据。当 PTlens 的数据库被加密时,Hugin 的作者试图建立一个免费的 XML 编码镜头数据库作为替代方案。这个数据库称为 LensFun,可以下载。它带有完整的编程接口,但您基本上只需要 XML 文件中您相机的信息即可。例如,曾经流行的尼康 Coolpix 995 的镜头校正参数可以在文件 compact-nikon.xml 中找到,该文件位于目录 \data\db 中。可以使用文本编辑器或 XML 查看器查看该文件

  <lens>
    <maker>Nikon</maker>
    <model>Standard</model>
    <mount>nikon995</mount>
    <cropfactor>4.843</cropfactor>
    <calibration>
      <distortion model="ptlens" focal="8.2" a="0" b="-0.019966" c="0" />
      <distortion model="ptlens" focal="10.1" a="0" b="-0.010931" c="0" />
      <distortion model="ptlens" focal="13.6" a="0" b="-0.002049" c="0" />
      <distortion model="ptlens" focal="18.4" a="0" b="0.003845" c="0" />
      <distortion model="ptlens" focal="23.4" a="0" b="0.006884" c="0" />
      <distortion model="ptlens" focal="28.3" a="0" b="0.008666" c="0" />
      <distortion model="ptlens" focal="31" a="0" b="0.009298" c="0" />
    </calibration>
  </lens>
从相机的技术规格表可以看出,尼康 Coolpix 995 的变焦范围为 8.2 – 31.0 mm,对应于 35 mm 胶片相机为 38 – 152 mm。这使得裁剪系数为 152 / 31 = 4.90,这大致对应于 XML 文件中给出的 4.843。通过桶形畸变校正提供的系数适用于六个焦距,即 8.2 mm、10.1 mm、13.6 mm、18.4 mm、23.4 mm、28.3 mm 和 31.0 mm。对于此镜头,系数 ac 设置为零,即畸变仅由二阶项 b 描述。请注意,许多镜头的 ac 参数也会有值,也应该以类似的方式进行插值。如果我们有一张使用尼康 Coolpix 995 设置为最短焦距拍摄的照片 DSCN0001.jpg,则可以使用 ImageMagick 通过以下方式对其进行校正

   magick DSCN0001.jpg -distort barrel '0.0 -0.019966 0.0' DSCN0001_pt.jpg
(文件扩展名 _pt 由 PTlens 用于标记已校正的图像。)对于提供的六个焦距,可以从 XML 文件中读取校正系数 b。对于其他焦距,可以通过对相邻两个焦距进行插值来确定合适的数值。作为替代方案,b 对焦距 f 的依赖关系可以用多项式近似
  b = 0.000005142 * f^3 - 0.000380839 * f^2 + 0.009606325 * f - 0.075316854
因此,第一步是使用从 EXIF 信息中读取的焦距来计算镜头校正参数 b,然后,在第二步中,使用此值作为 b 参数执行镜头校正(即桶形畸变)。Windows 部分显示了一个 VBScript 示例,其中使用了上述等式,并且焦距是通过 magick identify 从尼康 Coolpix 995 照片中提取的。

从头开始校准

基本方法

在确定镜头参数时,所有程序都依赖于相同的范式:理想的透视映射应将现实世界中的直线映射到图像中的直线。因此,如果已知一组现实世界中的点 P0、P1、...、Pn 位于一条直线上,则它们的图像 p0、p1、...、pn 也必须落在一条直线上。任何偏离此规则的行为都必须归因于镜头畸变。我们需要两点来确定定义直线的两个参数(例如,斜率和在 y 轴上的交点)。提供的每个额外的点将提供另一个等式来确定镜头校正参数。因此,如果我们的函数方法只有一个自由参数 b(如上面的尼康 Coolpix 995),我们必须在现实世界中的直线及其图像上提供至少三个点,以便确定所寻求的镜头校正参数 b。说得更具体一点:畸变模型只使用参数 b,即校正图像的坐标 X1, Y1 可以通过以下方式从数字照片的坐标计算得出
r = s * sqrt(x1^2 + y1^2)
X1 = [(1-b) + b r^2] * x1
Y1 = [(1-b) + b r^2] * y1
Y1 = k1 * X1 + k2
这导致每个点在同一条直线上都会产生一个等式
[(1-b) + b r^2] * y1 = k1 * [(1-b) + b r^2] * x1 + k2

with: r = s * sqrt(x1^2 + y1^2)
因此,三个现实世界中的点及其对应的图像点足以确定描述直线和镜头畸变 k1, k2, b 的参数。在实践中,现实世界中点的坐标很少已知,因此需要超过三个点来确定所寻求的参数。大多数校准软件使用直线的矩形网格(通常是棋盘格)来生成一组等式,然后通过非线性最小二乘拟合来计算映射参数。一些程序自行生成控制点集,通常使用预定义的模板;其他程序要求用户从校准图像中选择控制点。

使用 Hugin 确定镜头参数集

在下面,我们将演示如何使用 Hugin 确定一组镜头校正参数。Hugin 的网站上还有一个现成的“简单镜头校准教程”,但截至撰写本文时(2014 年),它似乎过于简单,无法提供后来可用于大量校正的可靠参数。首先,您必须获得合适的测试图案。基本上,在 ISO 216 A3 或类似尺寸的纸上打印的棋盘格图案,大约有 10 × 7 个方格,就可以了,而且经常被使用。但是,低成本变焦镜头(所谓的 变焦镜头)在校准期间应该设置为无限远对焦,因为它们真正的焦距可能与嵌入 EXIF 中的近距离对焦焦距有很大差异。对于定焦镜头,您也可以使用棋盘格测试图案,当校准鱼眼镜头时,这尤其推荐使用,因为可能很难找到足够大的现实世界物体来覆盖其视野。因此,尤其是在校准变焦镜头/变焦相机时,您应该使用 PTlens 网站 上建议的那样,拍摄现代建筑的照片。按照上面给出的说明进行操作。照片可能显示透视畸变
[IM Output]
透视
[IM Output]
非透视
启动 Hugin,点击第一个选项卡上的“添加图像...”按钮并打开校准图像。(有关 Hugin 界面截图,请参阅 hugin.sourceforge.net。)在选项卡底部将“优化”设置为“自定义参数”(这将添加一个名为“优化器”的新选项卡,否则您将看不到它)。在“拼接器”选项卡上,将“投影”设置为“矩形”。在“控制点”选项卡上,您会看到两次测试照片,并且可以通过在照片的两个版本中选择这些点组来定义位于同一直线上的点集。

但不要在两个版本中选择完全相同的点,这样会导致点在两个图像中都相同,因为这会导致优化器走捷径并确定一对一对应关系的参数。相反,您应该在图像两个版本的同一条线上选择不同的点。为了测试目的,您可以定义几个这样的点集,最好是在图像边缘附近,因为直线在那里的扭曲更严重。您会发现,在 Hugin 中定义这样的点集是一项相当繁琐的工作(这可能是 lensfun 数据库如此小的原因之一)。

然后切换到“优化器”选项卡,并通过按住 Ctrl 键并左键单击来选择要优化的参数。(查看选项卡顶部的提示。)我建议优化“偏航 (y)”、“俯仰 (p)”和镜头参数“a”、“b”和“c”。水平视场“Hfov (f)”是通过使用测试图像中的 EXIF 数据计算得出的,使用 FocalLengthIn35mmFilm 条目f
 Hfov = 2 × arctan (18 mm / f) 
其中 18 毫米是 35 毫米底片宽度的一半(尺寸为 36 × 24 毫米)。然后按下“立即优化!”按钮。对于广角镜头,生成的“a”、“b”和“c”参数应该低于 0.01,对于鱼眼镜头应该低于 0.1。如果这些值较大,则优化可能失败。如果是这样,请检查“控制点”选项卡上的点集:控制点可能顺序错误或与相应的线没有正确关联。优化器似乎对提供的起点集(从数学角度来说:起点向量)也很敏感,即,将所有参数设置为零可能不是正确的选择。您可以通过双击“优化器”选项卡上的值或激活选项卡页面右下角的“优化前编辑脚本”复选框来编辑起点向量。这将在优化之前弹出一个文本框,允许您编辑 Hugin 项目文件的相应部分。在重新启动优化器之前,将起点向量 a、b、c 恢复为a0.0 b0.0 c0.0(或其他合适的数值)。经验表明,将“a”设置为某个正值可能会有所帮助,尤其是对于鱼眼镜头。对于配备固定镜头的相机,只需进行一次校准。对于配备变焦镜头的相机,需要通过大约五个不同的焦距进行校准来覆盖整个焦距范围。确定好这样的参数集后,可以通过以下方式在 ImageMagick 中进行测试:

          

  magick calibration_image.jpg -distort barrel 'a b c' flat.jpg
将值a b c替换为刚刚确定的值。输出图像中的线应该完全直线,否则优化失败,需要使用不同的起点向量或更正的控制点集进行操作。

定义点集

对于严肃的校准,建议手动编辑 Hugin 项目文件并通过其他方式定义点坐标和点集。项目文件是一个扩展名为 PTO 的纯文本文件,您可以使用简单的文本编辑器打开它并提供点列表。它在# control points部分中的一行看起来像这样
  c n0 N0 x175.0 y87.8 X1533.3 Y62.6 t3
其中x, y是源图像(选项卡上的左侧图像)中的像素坐标,X, Y是目标图像(选项卡上的右侧图像)中的像素坐标——在本例中实际上是同一图像的两个版本。(通常,它们将是全景图中彼此相邻的两个不同的图像。)简介c n0 N0是标准代码,尾随部分t3是相关直线的编号,从索引 3 开始。从上面的例子中可以看出,像素坐标可能包含小数部分。当然,x, yX, Y必须位于同一直线上。但是,它们不能相同,因为在这种情况下优化器将拒绝工作(见上文)。确保这一点的最简单方法是在两个图像中使用相同的点,但在目标坐标中反向排序,例如,在左侧图像中使用 p1、p2、p3、p4,在右侧图像中使用 P4、P3、P2、P1。使用点拾取工具确定源图像中的像素坐标。您可以使用任何图像查看器执行此操作,尤其是那些可以存储此类数据的查看器。一个与平台无关的工具是 Fiji。我(在 Windows 下工作)使用 WinMorph 中的多段线来实现这一点。您应该在选择点时遵循预定义的策略,例如,在每条(或多或少)水平线上选择相同数量的点,从左到右(即,在整个图像中遵循之字形,就像电视机中的阴极射线束一样)。这样的策略将简化目标点坐标的排序。然后可以通过手动或软件工具的方式建立定义源和目标点坐标的文本文件行。(我使用 Excel VBA 子例程来执行此任务。)准备好后,将点列表复制到 PTO 文件的相应部分,保存它并使用 Hugin 重新打开它。结果应该像这样
[IM Output]
Hugin 中的控制点网格
在 ZIP 文件 olympus_c2500l.zip中提供了一个现成的示例,包括校准图像和相应的 Hugin 项目。

从相机创建的缩略图重新设计

在某些情况下,我们已经有一对图像,其中一张是桶形失真,另一张已经过校正。这种校正可能由其他镜头校正软件执行,而这些软件不会告诉我们校正参数。此外,许多当代相机(2019 年)提供针对 JPEG 图像进行内部镜头校正的功能。但是,此功能通常不应用于 RAW 图像。(嗯,它是原始的。)尽管如此,RAW 图像包含一个 JPEG 预览,该预览已经由相机应用了校正。ImageMagick 可以使用 dcraw 读取 RAW 图像。因此,可以将原始图像用 ImageMagick 转换为 JPEG,而不进行镜头校正,并将结果与内部校正的 JPEG 缩略图进行比较。对于这种图像对,可以直观地计算校正参数。通过在两个图像中选择相应的点对,可以直接建立rR之间的关系。
[RAW 图像]
原始图像(桶形失真) [校正图像]
校正后的缩略图(用于重新设计)
如上例所示,我们可以自由选择哪些点对;这些点对不必遵循直线,甚至不必位于几何图形上。我们只需要填写一个包含rR对应值的表格,然后计算回归曲线,例如使用
电子表格 图表。
[Calabration]
校准点
[Regression]
回归(缩放)
因此,ImageMagick 命令行是

  magick barrel.jpg -distort barrel '0.0099 -0.0678 0.0014 1.0511' flat.jpg
您也可以将相同的命令直接应用于 DNG 相机格式图像“barrel.dng”。

镜头校正示例

房车

[IM Output]
原始图像
[IM Output]
校正后
[IM Output]
差异
左侧的房车原始照片必须在黄昏时从相当近的距离拍摄,因为摄影师身后的陡坡限制了空间。(糟糕的照明条件解释了蓝色色调,该色调源于后期处理中的严重亮化。)原始照片显示出明显的桶形失真,尤其是在图像顶部的水平条纹和建筑物后角中。拍摄此照片所使用的尼康 Coolpix 995 可以在 PTlens 的数据库中找到,因此可以轻松地校正失真,如中间所示。右侧的图像显示了两张照片的灰度版本之间的差异,通过对两张照片进行减法运算,然后取反以及进行极端裁剪和伽玛校正计算得出。同样,校正效果可以通过顶部水平条纹最直观地说明。白色圆圈(表示零差异)是由于非缩放限制造成的:直径等于图像较小尺寸的圆圈上的点保持不变。

GoPro 扁平化

GoPro 相机镜头产生明显的桶形失真,这似乎是其品牌的一部分。例如,GoPro Hero 3+ 银色版配备了鱼眼镜头,固定焦距为 2.77 毫米,如果使用整个感光区域,则对应于 35 毫米胶片中的 16 毫米焦距。GoPro Hero 3+ 有三种照片模式
  • 1000 万像素 = 3680 × 2760 像素广角(35 毫米胶片中的 16 毫米)
  • 700 万像素 = 3072 × 2304 像素广角(35 毫米胶片中的 16 毫米)
  • 500 万像素 = 2624 × 1968 像素中角(35 毫米胶片中的 23 毫米)
GoPro Hero 3+ 配备 1/2.3 英寸传感器,其裁切系数为 5.64。(这使得 35 毫米胶片中的焦距仅为 15.62 毫米,EXIF 信息中提供的 16 毫米可能是由于四舍五入造成的。)前两种模式似乎使用了整个感光区域;降低的解析度显然是通过子采样实现的。因此,失真参数相同,这可以在实践中得到证明。500 万像素模式显然只使用感光区域的一部分,因为 3680 / 2624 × 16 ≈ 23。镜头参数可以确定为
  • 广角
    • a = 0.06335
    • b = -0.18432
    • c = -0.13009
  • 中角
    • a = 0.01359
    • b = -0.06034
    • c = -0.10618
理论上,第二种模式的参数可以从第一种模式中推导出,因为半径riRi通过比例因子 κ = 3680 / 2624 = 1.402 耦合,这导致
  • a2 = a1 / κ³
  • b2 = b1 / κ²
  • c2 = c1 / κ
以上参数是通过独立优化得出的,与这些理论值相差不大。相应地,各种视频模式的参数可以通过优化或从该模式使用的传感器区域的一部分推导出。对于视频,无法从 EXIF 数据中推导出水平视场。它可以从使用的感光区域计算得出(通过在受控条件下拍摄素材来确定),或者与其他参数一起估计,即作为优化中的自由参数。HD 视频(1920 × 1080)的参数是
  • a = 0.030530
  • b = -0.124312
  • c = -0.038543
这些参数可用于使用 ImageMagick 进行逐帧校正。或者,可以使用它们通过 AVIsynth 插件 DeBarrel“扁平化”整个视频,该插件也使用 Panorama Tools 镜头校正模型。

两个键盘by el_supremo

我拍摄的两个键盘的照片有非常明显的桶形失真,因为它是用 17 毫米焦距拍摄的。
[IM Output]
这种类型的畸变可以通过例如佳能的Digital Photo Professional(我有一台佳能50D相机)来校正。其他单反相机制造商通常提供软件来对他们的镜头进行这种校正,但我希望看看上面的示例在这个照片上效果如何。第一步是访问LensFun 网站并下载最新版本的相机数据库。解压缩软件包(winzip可以在 Windows 中解压缩 .tar.gz 文件),然后在“lensfun/data/db”目录中查找与您的相机制造商相对应的文件。在我的情况下,我查看了“slr-canon.xml”,它可以使用任何文本编辑器进行编辑。现在我找到了正在使用的特定镜头的信息,在这种情况下是“EF-S 17-85mm”。该镜头的信息如下所示
<lens>
  <maker>Canon</maker>
  <model>Canon EF-S 17-85mm f/4-5.6 IS USM</model>
  <mount>Canon EF-S</mount>
  <cropfactor>1.6</cropfactor>
  <calibration>
    <distortion model="ptlens" focal="17" a="0.021181" b="-0.055581" c="0" />
    <distortion model="ptlens" focal="20" a="0.019344" b="-0.043786" c="0" />
    <distortion model="ptlens" focal="22" a="0.015491" b="-0.026682" c="0" />
    <distortion model="ptlens" focal="28" a="0.008084" b="-0.007472" c="0" />
    <distortion model="ptlens" focal="30" a="0.005522" b="-0.001763" c="0" />
    <distortion model="ptlens" focal="35" a="0.003149" b="0.002207" c="0" />
    <distortion model="ptlens" focal="44" a="0" b="0.008269" c="0" />
    <distortion model="ptlens" focal="53" a="0" b="0.008792" c="0" />
    <distortion model="ptlens" focal="61" a="0" b="0.00738" c="0" />
    <distortion model="ptlens" focal="72" a="0" b="0.006226" c="0" />
    <distortion model="ptlens" focal="78" a="0" b="0.007095" c="0" />
    <distortion model="ptlens" focal="85" a="0" b="0.007288" c="0" />
  </calibration>
</lens>
校准条目给出了从 17 毫米到 85 毫米的一系列焦距的畸变值。如果我需要的焦距位于这两个值之间,我可以选择最接近的值,也可以对这些值进行插值。由于我正在校正的照片是在 17 毫米处拍摄的,因此我需要第一行校准信息中的信息。这给了我以下值:  a="0.021181"  b="-0.055581"  c="0" 这些是用于校正镜头畸变的三个参数。但是对于某些较旧版本的 IM 来说,桶形畸变校正需要第四个参数 d。幸运的是,可以使用这个简单的公式从其他三个参数中轻松计算出 d 的值:  d = 1-a-b-c  这意味着:  d="1.0344"
如果未提供为畸变参数,IM 将自动计算出 'd' 的值,但某些旧版本的 IM 不会这样做。
这使得实际的桶形畸变,以校正镜头畸变...

    magick keyboards.jpg \
          -distort barrel "0.021181 -0.055581 0" \
          keyboards_ptlens.jpg
[IM Output]
当然,在完成图像处理之前,你不应该保存为 JPEG,因为 JPEG 是有损压缩。
在原始照片中,畸变在音乐架底部和上部键盘处特别明显。这些畸变在输出照片中几乎完全消失了。将此结果与佳能软件获得的结果进行视觉比较,结果基本相同。El-Supremo