使用OpenCV校准鱼眼镜头的方法


Posted in Python onNovember 26, 2020

01.简介

当我们使用的鱼眼镜头视角大于160°时,OpenCV中用于校准镜头“经典”方法的效果可能就不是和理想了。即使我们仔细遵循OpenCV文档中的步骤,也可能会得到下面这个奇奇怪怪的照片:

使用OpenCV校准鱼眼镜头的方法

如果小伙伴也遇到了类似情况,那么这篇文章可能会对大家有一定的帮助。

从3.0版开始,OpenCV包含了cv2.fisheye可以很好地处理鱼眼镜头校准的软件包。但是,该模块没有针对读者的相关的教程。

02.相机参数获取

校准镜头其实只需要下面2个步骤。

  • 利用OpenCV计算镜头的2个固有参数。OpenCV称它们为K和D,我们只需要知道它们是numpy数组外即可。
  • 通过K和D对图像进行去畸变矫正。

计算K和D

  • 下载棋盘格图案并将其打印在纸上(字母或A4尺寸)。大家要尽量将这张纸粘在坚硬且平坦的物体表面,例如一块硬纸板上。因为这里的关键是直线必须是直线
  • 将图案放在相机前面拍摄一些图像,图案要取在不同的位置和角度。这里的关键是图案需要以不同的方式出现失真(以便OpenCV尽可能多地了解镜头相关参数)。

使用OpenCV校准鱼眼镜头的方法

我们先将这些图片保存在JPG文件夹中。

现在我们只需要将此Python脚本片段复制到calibrate.py先前保存这些图像的文件夹中的文件中,就可以对其进行命名。

import cv2
assert cv2.__version__[0] == '3', 'The fisheye module requires opencv version >= 3.0.0'
import numpy as np
import os
import glob
CHECKERBOARD = (6,9)
subpix_criteria = (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC+cv2.fisheye.CALIB_CHECK_COND+cv2.fisheye.CALIB_FIX_SKEW
objp = np.zeros((1, CHECKERBOARD[0]*CHECKERBOARD[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
_img_shape = None
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
images = glob.glob('*.jpg')
for fname in images:
  img = cv2.imread(fname)
  if _img_shape == None:
    _img_shape = img.shape[:2]
  else:
    assert _img_shape == img.shape[:2], "All images must share the same size."
  gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  # Find the chess board corners
  ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
  # If found, add object points, image points (after refining them)
  if ret == True:
    objpoints.append(objp)
    cv2.cornerSubPix(gray,corners,(3,3),(-1,-1),subpix_criteria)
    imgpoints.append(corners)
N_OK = len(objpoints)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
rms, _, _, _, _ = \
  cv2.fisheye.calibrate(
    objpoints,
    imgpoints,
    gray.shape[::-1],
    K,
    D,
    rvecs,
    tvecs,
    calibration_flags,
    (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6)
  )
print("Found " + str(N_OK) + " valid images for calibration")
print("DIM=" + str(_img_shape[::-1]))
print("K=np.array(" + str(K.tolist()) + ")")
print("D=np.array(" + str(D.tolist()) + ")")

运行python calibrate.py。如果一切顺利,脚本将输出如下内容:

Found 36 images for calibration
DIM=(1600, 1200)
K=np.array([[781.3524863867165, 0.0, 794.7118000552183], [0.0, 779.5071163774452, 561.3314451453386], [0.0, 0.0, 1.0]])
D=np.array([[-0.042595202508066574], [0.031307765215775184], [-0.04104704724832258], [0.015343014605793324]])

03.图像畸变矫正

获得K和D后,我们可以对以下情况获得的图像进行失真矫正:我们需要取消失真的图像与校准期间捕获的图像具有相同的尺寸。也可以将边缘周围的某些区域裁剪掉,来保证使未失真图像的整洁。通过undistort.py使用以下python代码创建文件:

DIM=XXX
K=np.array(YYY)
D=np.array(ZZZ)
def undistort(img_path):
  img = cv2.imread(img_path)
  h,w = img.shape[:2]
  map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
  undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
  cv2.imshow("undistorted", undistorted_img)
  cv2.waitKey(0)
  cv2.destroyAllWindows()
if __name__ == '__main__':
  for p in sys.argv[1:]:
    undistort(p)

现在运行python undistort.py file_to_undistort.jpg。

使用OpenCV校准鱼眼镜头的方法

矫正前

使用OpenCV校准鱼眼镜头的方法

矫正后

如果大家仔细观察,可能会注意到一个问题:原始图像中的大部分会在此过程中被裁剪掉。例如,图像左侧的橙色RC汽车只有一半的车轮保持在未变形的图像中。实际上,原始图像中约有30%的像素丢失了。小伙伴们可以思考思考如果我们想找回丢失的像素该这么办呢?

到此这篇关于使用OpenCV校准鱼眼镜头的方法的文章就介绍到这了,更多相关OpenCV校准鱼眼镜内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python调用短信猫控件实现发短信功能实例
Jul 04 Python
python操作sqlite的CRUD实例分析
May 08 Python
Python实现的RSS阅读器实例
Jul 25 Python
python绘制评估优化算法性能的测试函数
Jun 25 Python
python 3.7.4 安装 opencv的教程
Oct 10 Python
pygame实现俄罗斯方块游戏(基础篇1)
Oct 29 Python
python反转列表的三种方式解析
Nov 08 Python
python 实现矩阵填充0的例子
Nov 29 Python
Python StringIO如何在内存中读写str
Jan 07 Python
Python matplotlib画曲线例题解析
Feb 07 Python
tensorflow下的图片标准化函数per_image_standardization用法
Jun 30 Python
python绘制汉诺塔
Mar 01 Python
最新PyCharm 2020.2.3永久激活码(亲测有效)
Nov 26 #Python
Django-celery-beat动态添加周期性任务实现过程解析
Nov 26 #Python
Django celery异步任务实现代码示例
Nov 26 #Python
Django通过设置CORS解决跨域问题
Nov 26 #Python
Django利用elasticsearch(搜索引擎)实现搜索功能
Nov 26 #Python
python模拟点击在ios中实现的实例讲解
Nov 26 #Python
如何在 Matplotlib 中更改绘图背景的实现
Nov 26 #Python
You might like
利用PHP函数计算中英文字符串长度的方法
2014/11/11 PHP
PHP基于反射机制实现插件的可插拔设计详解
2016/11/10 PHP
javascript的console.log()用法小结
2012/05/31 Javascript
jQuery中校验时间格式的正则表达式小结
2013/09/22 Javascript
javascript函数作用域学习示例(js作用域)
2014/01/13 Javascript
把jQuery的类、插件封装成seajs的模块的方法
2014/03/12 Javascript
window.open()详解及浏览器兼容性问题示例探讨
2014/05/29 Javascript
基于jquery实现的自动补全功能
2015/03/12 Javascript
javascript验证手机号和实现星号(*)代替实例
2016/08/16 Javascript
11行JS代码制作二维码生成功能
2018/03/09 Javascript
vee-validate vue 2.0自定义表单验证的实例
2018/08/28 Javascript
使用angularjs.foreach时return的问题解决
2018/09/30 Javascript
小程序实现列表删除功能
2018/10/30 Javascript
使用React手写一个对话框或模态框的方法示例
2019/04/25 Javascript
electron实现静默打印的示例代码
2019/08/12 Javascript
vue2.0 watch里面的 deep和immediate用法说明
2020/10/30 Javascript
vant中的toast层级改变操作
2020/11/04 Javascript
使用url_helper简化Python中Django框架的url配置教程
2015/05/30 Python
Python编写电话薄实现增删改查功能
2016/05/07 Python
python解决Fedora解压zip时中文乱码的方法
2016/09/18 Python
Python聊天室程序(基础版)
2018/04/01 Python
解决pyinstaller打包发布后的exe文件打开控制台闪退的问题
2019/06/21 Python
Python可以用来做什么
2020/11/23 Python
python unichr函数知识点总结
2020/12/16 Python
美国领先的水果篮送货公司和新鲜水果供应商:The Fruit Company
2018/02/13 全球购物
瑞典在互联网上最大的宠物商店:Animail
2020/10/31 全球购物
个人求职信范文分享
2014/01/06 职场文书
考试不及格检讨书
2014/01/09 职场文书
个人融资协议书
2014/10/02 职场文书
武当山导游词
2015/02/03 职场文书
劳动仲裁撤诉申请书
2015/05/18 职场文书
鸦片战争观后感
2015/06/09 职场文书
预备党员入党感想
2015/08/10 职场文书
vue使用节流函数的踩坑实例指南
2021/05/20 Vue.js
详解SpringBoot异常处理流程及原理
2021/06/21 Java/Android
CSS 实现角标效果的完整代码
2022/06/28 HTML / CSS