【问题标题】:Correcting barrel lens distortion in an x,y series in R校正 R 中 x,y 系列中的桶形透镜失真
【发布时间】:2014-09-29 08:43:34
【问题描述】:

编辑:理想情况下,我想使用与 ImageMagick 的 -distort 函数相同的算法,但在 R 中实现,以便转换原始 x,y 坐标,而不是图像。使用 ImageMagick 还可以让我直观地证明不失真的有效性。

问题

我有一个 x,y 系列,是通过跟踪软件对视频的分析产生的。视频中的原始图像有一些桶形镜头畸变,我想纠正一下,以提高跟踪坐标的准确性。

我可以使用 ImageMagick 中的扭曲运算符执行看起来合适的校正,例如:

convert input.jpg -distort barrel '0 -0.022 0' output.jpg

现在我知道我可以将此校正应用于视频中的每一帧(在跟踪之前),但这似乎不是最佳选择,因为我有几十个视频,每个视频都包含 >7e4 帧。似乎在跟踪后将校正应用于 x,y 坐标本身会容易得多。

来自 ImageMagick documentation,桶形失真方程为:

Rsrc = r * (Ar^3 + Br^2 + C*r + D)

其中“r”是目标半径,“Rsrc”是从中获取像素颜色的源像素。半径被归一化,因此对于输入图像的最小宽度或高度的一半,半径 = '1.0'。"

但我不知道如何在 R 中实现这一点以转换 x,y 系列。任何人都可以提供任何帮助吗?谢谢!

到目前为止我已经尝试过什么

我已经尝试了自己的函数,修改了我找到的here 的一个简单算法,但这似乎会引入更大的桶形失真(如果有的话)(并且其极性似乎无法反转):

undistortFun <- function(X, Y, strength) {

    imWidth <- 640
    imHeight <- 480

    radius_u <- sqrt(imWidth^2 + imHeight^2) / strength

    normX <- X - (imWidth / 2)
    normY <- Y - (imHeight / 2)

    distance <- sqrt(normX^2 + normY^2)
    r <- distance / radius_u

    theta <- ifelse(r == 0, 1, atan(r) / r)

    newX <- (imWidth / 2) + theta * normX
    newY <- (imHeight / 2) + theta * normY

    return(data.frame(X = newX, Y = newY))

}

类似问题

我发现了两个类似的问题,herehere,但这些问题涉及不失真的图像而不是原始 x,y 坐标,并且是用我不熟悉的 Java 和 C++ 实现的。

【问题讨论】:

  • 几乎没有发布 R 光学校正算法代码 AFAIK。但是,如果您提供了您称为“其他地方”的桶形校正算法的来源,则更容易发表评论。 (请注意,我没有拒绝建议,如果您的第一次尝试增加了明显的失真,您应该反转极性 :-))
  • 这个问题似乎是题外话,因为它是关于图像处理方法的开发,它并不是一个真正的编程问题(因为你的代码运行没有错误,它只是不会产生你想要的结果.) 我可能会检查是否有更合适的a different stackexchange site。或者至少要清楚你希望实现的方法的细节。
  • @MrFlick 我已经编辑了这个问题,希望它更清楚。
  • 这真的无济于事,除非你能确切地告诉我们 ImageMagick 的 -distort 函数使用什么算法。
  • @CarlWitthoft 我已经添加了源代码——颠倒极性是我的第一个想法(信不信由你:-P),但函数的作者表示不能反转转换,并且恐怕我不明白该功能实际上做得如何足以解决它!

标签: r image-processing geometry distortion


【解决方案1】:

通过使用 ImageMagick 失真算法修改问题中提供的函数,我得到了一个令人满意的解决方案:

Rsrc = r * ( Ar^3 + Br^2 + C*r + D )

像这样:

undistortFun <- function(x, y, a, b, c, d = 1, imWidth = 640, imHeight = 480) {

    normX <- X - (imWidth / 2)
    normY <- Y - (imHeight / 2)

    radius_u <- sqrt(imWidth^2 + imHeight^2)

    r <- sqrt(normX^2 + normY^2) /  radius_u

    Rsrc <- r * (a*r^3 + b*r^2 + c*r + d)

    theta <- ifelse(Rsrc == 0, 1, 1 / atan(Rsrc) * Rsrc)

    newX <- (imWidth / 2) + theta * normX
    newY <- (imHeight / 2) + theta * normY

    return(data.frame(X = newX, Y = newY))
}

虽然我不确定 theta 的计算,但指定零失真 (a=0, b=0, c=0) 仍然会导致转换。尽管如此,它似乎在这些示例中实现了我想要的效果:

原始 x,y 数据图:

调整后的 x,y 数据图(其中:a =0,b= -0.02,c = 0):

【讨论】:

  • 绝妙的解决方案。在这种情况下,X 和 Y 是否位于: normX
猜你喜欢
  • 1970-01-01
  • 2012-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多