【问题标题】:OpenCV : how to provide matrix for 'undistort' if I know lens correction factor in Gimp?OpenCV:如果我知道 Gimp 中的镜头校正因子,如何为“不失真”提供矩阵?
【发布时间】:2017-03-25 13:36:07
【问题描述】:

我从具有强烈鱼眼效果的 IP 摄像机获取图像。我发现在 Gimp 中,我可以通过应用“主要”值为 -30(所有其他参数保持为零)的镜头失真滤镜来获得大部分直线。

现在我需要使用 OpenCV 临时执行此操作。我收集到 imgproc 中的 undistort 函数将是正确的调用方法。但是如何生成正确的相机和畸变矩阵呢?我看到有一个calibrateCamera 函数,但您似乎需要计算机视觉方面的博士学位才​​能使用它。我没有任何线索。既然我知道一个参数,那么一定有一种简单的方法可以将其转换为“不失真”所期望的矩阵?

注意:我只需要径向畸变系数,我对切向畸变不感兴趣。

【问题讨论】:

  • 其实有一个opencv为calibration提供的样本。为此,您需要的只是棋盘格图像列表(大约 20 个应该不错)。由您想要的相机拍摄。它将为您提供所有必需的参数(失真系数、内在参数等)。然后你可以使用opencv的'undistort'功能来校正你的图像。
  • 您需要在 default.xml 中更改 xml 文件的名称,其中包含您的图像地址、内部正方形的数量及其在现实世界中的尺寸。 tadaa 你有你需要的参数:-)
  • @Optimus1072 非常感谢;我设法靠近;我使用示例从源代码构建 opencv,我有 9 个棋盘图像 - 我已经将它们全部“平行”:imgur.com/a/JByDH,这样好吗? - 我运行./bin/cpp-example-calibration -w=5 -h=4 -pt=chessboard -o=amcrest.yml -op -oe image_list.xml。但这不会“输出”任何东西。它会打开一个窗口,依次显示输入图像,然后退出。我找不到文件“amcrest.yml”,所以我一定做错了什么?
  • @Optimus1072 在了解num-corners = (num-black-squares - 1) * 2 之后,它现在可以工作了。你可以发表你的评论作为答案,然后我可以关闭这个问题。再次感谢。
  • 一般 15-20 张图像被认为是好的,我想你将不得不使用鱼眼不失真功能来校正你的图像。

标签: opencv


【解决方案1】:

opencv 为calibration 提供了一个示例。为此,您需要的只是棋盘格图像列表(大约 20 个应该不错)。由您想要的相机拍摄。它将为您提供所有必需的参数(失真系数、内在参数等)。然后你可以使用opencv的'undistort'功能来校正你的图像。 您需要在 default.xml 中更改(或者您可以创建自己的 .xml)xml 文件的名称,其中包含图像的地址、内部正方形的数量及其在现实世界中的尺寸。

tadaa 你有你需要的参数:-)

【讨论】:

  • 现在只用了九张图片,看起来已经很准确了。
【解决方案2】:

对于那些想知道校准工具来自哪里的人。似乎必须从源代码构建它。这就是我在 Linux 上所做的:

git clone https://github.com/opencv/opencv.git
cd opencv
git checkout -b 3.1.0 3.1.0  # make sure we build that version
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_EXAMPLES=ON ..
make -j4

然后进行校准:

./bin/cpp-example-calibration -w=8 -h=6 -o=camera.yml -op -oe -su image_list.xml

-su 可让您验证图像在未失真后的外观。 -w-h 参数采用“内角”,这不是国际象棋图案中的方格数,而是 (num-black-squares - 1) * 2

以下是透视变换的最终应用方式,使用 Scala 和 JavaCV:

import org.bytedeco.javacpp.indexer.FloatRawIndexer
import org.bytedeco.javacpp.opencv_core.Mat
import org.bytedeco.javacpp.{opencv_core, opencv_imgcodecs, opencv_imgproc}
import java.io.File

// from the camera_matrix > data part of the yml:
val cameraFocal = 1.4656877976320607e+03
val cameraCX    = 1920.0/2
val cameraCY    = 1080.0/2

val cameraMatrixData = Array[Double](
  cameraFocal, 0.0        , cameraCX,
  0.0        , cameraFocal, cameraCY,
  0.0        , 0.0        , 1.0
)

// from the distortion_coefficients of the yml:
val distMatrixData = Array[Double](
  -4.016824381742e-01, 4.368842493074e-02, 0.0, 0.0, 1.096412142704e-01
)

def run(in: File, out: File): Unit = {
  val matOut  = new Mat
  val camMat  = new Mat(3, 3, opencv_core.CV_32FC1)
  val camIdx  = camMat.createIndexer[FloatRawIndexer]
  for (row <- 0 until 3) {
    for (col <- 0 until 3) {
      camIdx.put(row, col, cameraMatrixData(row * 3 + col).toFloat)
    }
  }
  val distVec = new Mat(1, 5, opencv_core.CV_32FC1)
  val distIdx = distVec.createIndexer[FloatRawIndexer]
  for (col <- 0 until 5) {
    distIdx.put(0, col, distMatrixData(col).toFloat)
  }

  val matIn   = opencv_imgcodecs.imread(in.getPath)
  opencv_imgproc.undistort(matIn, matOut, camMat, distVec)
  opencv_imgcodecs.imwrite(out.getPath, matOut)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    • 2012-09-19
    • 1970-01-01
    • 2018-06-04
    相关资源
    最近更新 更多