针孔相机模型图像去畸变

针对畸变参数,k1,k2,k3,k4描述径向的畸变参数,p1,p2描述切向的畸变参数,一般k4不使用,默认为0.

方法一

方法一是使用cv2.undistort函数,undistort函数依据相机内参与畸变系数対原图像进行去畸变。

import cv2
import numpy as np

parameter_mapping = {
    # 内参
    'K': [[560.377864062484, 0.0, 653.920208824032], [0.0, 560.333488463768, 405.051274966661],
                           [0.0, 0.0, 1.0]],
    # 畸变系数( k1 , k2 , p1 , p2 , k3 )
    'D': [-0.315795863414683, 0.132439325545726, 3.30224273178591e-05, -0.000236840010193784, -0.0289107949906846]
}

if __name__ == '__main__':
    image_file = './origin_img.jpg'
    img = cv2.imdecode(np.fromfile(image_file, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
    undistortion_img = cv2.undistort(img, np.array(parameter_mapping["K"]),
                        np.array(parameter_mapping["D"]), None, None)
    cv2.imencode('.jpg', undistortion_img)[1].tofile('./undistortion_img.jpg')

方法二

方法二是使用cv2.initUndistortRectifyMap和cv2.remap函数,initUndistortRectifyMap函数用于计算原图像与去畸变图像的转换关系,remap函数可以将一幅图像中某位置的像素放置到另一个图片指定位置。

import cv2
import numpy as np

parameter_mapping = {
    # 内参
    'K': [[560.377864062484, 0.0, 653.920208824032], [0.0, 560.333488463768, 405.051274966661],
                           [0.0, 0.0, 1.0]],
    # 畸变系数( k1 , k2 , p1 , p2 , k3 )
    'D': [-0.315795863414683, 0.132439325545726, 3.30224273178591e-05, -0.000236840010193784, -0.0289107949906846]
}

if __name__ == '__main__':
    image_file = './origin_img.jpg'
    img = cv2.imdecode(np.fromfile(image_file, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
    mapx,mapy = cv2.initUndistortRectifyMap(np.array(parameter_mapping["K"]), np.array(parameter_mapping["D"]), None, None, (img.shape[1],img.shape[0]),cv2.CV_16SC2)
    undistortion_img = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
    cv2.imencode('.jpg', undistortion_img)[1].tofile('./undistortion_img.jpg')

区别与联系

undistort函数是initUndistortRectifyMap和remap两个函数的合并。
在硬件设备上运行时,摄像头实时对原图像进行去畸变,使用undistort函数占用cpu内核较高,而使用initUndistortRectifyMap和remap的方法,初始化时率先计算出重映射参数并保存下来,然后针对每一帧图像直接使用之前计算好的重映射参数进行remap映射,计算复杂度比方法一小很多。

鱼眼相机模型图像去畸变

在此采用的是cv::fisheye描述方法,畸变参数只有四个:k1,k2,k3,k4,这是opencv专门为鱼眼相机创建的模型,也对应着kalibr中的pinhole-equidistant模型。鱼眼相机模型去畸变后图像左右上下边缘可能存在黒框,需要进一步裁切处理。

方法一

方法一是使用cv2.fisheye.undistortImage函数。

import cv2
import numpy as np

parameter_mapping = {
    # 内参
    'K': [[562.8536266451736, 0.0, 652.0363818527527], [0.0, 562.7074689373112, 405.06204162772434],
                           [0.0, 0.0, 1.0]],
    # 新的内参,默认与内参相同,如果有平移缩放,则可通过cv::getOptimalNewCameraMatrix()函数计算
    'new_K': [[298.6393797450104, 0.0, 659.9713311562739], [0.0, 298.56183125788215, 404.8096582172302],
                           [0.0, 0.0, 1.0]],
    # 畸变系数( k1 , k2 , k3 , k4)
    'D': [-0.008989658783934219, 0.02224293904563013, -0.0145636811902354, 0.005863283995426509]
}

if __name__ == '__main__':
    image_file = './origin_img.jpg'
    img = cv2.imdecode(np.fromfile(image_file, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
   undistortion_img = cv2.fisheye.undistortImage(img, np.array(parameter_mapping["K"]), np.array(parameter_mapping["D"]), np.eye(3), np.array(parameter_mapping["new_K"]), (img.shape[1],img.shape[0]))
    cv2.imencode('.jpg', undistortion_img)[1].tofile('./undistortion_img.jpg')

方法二

方法二是使用cv2.fisheye.initUndistortRectifyMap和cv2.remap函数。

import cv2
import numpy as np

parameter_mapping = {
    # 内参
    'K': [[562.8536266451736, 0.0, 652.0363818527527], [0.0, 562.7074689373112, 405.06204162772434],
                           [0.0, 0.0, 1.0]],
    # 新的内参,默认与内参相同,如果有平移缩放,则可通过cv::getOptimalNewCameraMatrix()函数计算
    'new_K': [[298.6393797450104, 0.0, 659.9713311562739], [0.0, 298.56183125788215, 404.8096582172302],
                           [0.0, 0.0, 1.0]],
    # 畸变系数( k1 , k2 , k3 , k4)
    'D': [-0.008989658783934219, 0.02224293904563013, -0.0145636811902354, 0.005863283995426509]
}

if __name__ == '__main__':
    image_file = './origin_img.jpg'
    img = cv2.imdecode(np.fromfile(image_file, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
    mapx,mapy = cv2.fisheye.initUndistortRectifyMap(np.array(parameter_mapping["K"]), np.array(parameter_mapping["D"]), np.eye(3), np.array(parameter_mapping["new_K"]), (img.shape[1],img.shape[0]),cv2.CV_16SC2)
    undistortion_img = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
    cv2.imencode('.jpg', undistortion_img)[1].tofile('./undistortion_img.jpg')

区别与联系

undistortImage函数是initUndistortRectifyMap和remap两个函数的合并。
在硬件设备上运行时,摄像头实时对原图像进行去畸变,使用undistortImage函数占用cpu内核较高,而使用initUndistortRectifyMap和remap的方法,初始化时率先计算出重映射参数并保存下来,然后针对每一帧图像直接使用之前计算好的重映射参数进行remap映射,计算复杂度比方法一小很多。

参考文献

https://zhuanlan.zhihu.com/p/137053640
https://blog.csdn.net/Thomson617/article/details/103987952

GitHub 加速计划 / opencv31 / opencv
77.38 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:2 个月前 )
c3747a68 Added Universal Windows Package build to CI. 12 天前
9b635da5 - 12 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐