我从IP相机获取具有强烈鱼眼效果的图像。我发现在Gimp中,我可以通过应用“主”值-30(所有其他参数保持为零)的镜头失真滤镜来获得大部分直线。
现在我需要使用OpenCV临时做这件事。我认为imgproc
中的undistort函数是正确的调用方式。但是如何生成正确的相机和失真矩阵呢?我看到有一个calibrateCamera功能,但似乎你需要一个计算机视觉博士才能使用它。我没有线索。既然我知道一个参数,那么必须有一种简单的方法将它转换为'undistort'所期望的矩阵吗?
注意:我只需要径向失真系数,我对切向失真不感兴趣。
答案 0 :(得分:1)
opencv为calibration提供了一个示例。为此你需要的是棋盘图像列表(大约20个应该是好的)。由您想要的相机拍摄。它将为您提供所有必需的参数(失真系数,内部参数等)。然后你可以使用opencv的'undistort'功能来纠正你的形象。 您需要在default.xml中更改(或者您可以创建自己的.xml)包含图像地址的xml文件的名称,内部正方形的数量及其在现实世界中的维度。
tadaa你有所需的参数: - )
答案 1 :(得分:0)
对于那些想知道校准工具来自哪里的人。似乎必须从源头构建它。这就是我在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)
}