使用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 相关文章推荐
Django中使用group_by的方法
May 26 Python
深入理解python中的atexit模块
Mar 07 Python
基于python(urlparse)模板的使用方法总结
Oct 13 Python
Python模块搜索路径代码详解
Jan 29 Python
利用Python在一个文件的头部插入数据的实例
May 02 Python
解决pip install的时候报错timed out的问题
Jun 12 Python
深入了解如何基于Python读写Kafka
Dec 31 Python
使用sklearn的cross_val_score进行交叉验证实例
Feb 28 Python
django之导入并执行自定义的函数模块图解
Apr 01 Python
Django如何创作一个简单的最小程序
May 12 Python
使用python+pygame开发消消乐游戏附完整源码
Jun 10 Python
Python OpenCV实现传统图片格式与base64转换
Jun 13 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
使用sockets:从新闻组中获取文章(一)
2006/10/09 PHP
php按百分比生成缩略图的代码分享
2014/05/10 PHP
php图片添加文字水印实现代码
2016/03/15 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
2017/11/17 PHP
laravel5.6中的外键约束示例
2019/10/23 PHP
Firefox中通过JavaScript复制数据到剪贴板(Copy to Clipboard 跨浏览器版)
2013/11/22 Javascript
Node.js中HTTP模块与事件模块详解
2014/11/14 Javascript
js实现滑动触屏事件监听的方法
2015/05/05 Javascript
jQuery操作复选框(CheckBox)的取值赋值实现代码
2017/01/10 Javascript
基于JS实现仿百度百家主页的轮播图效果
2017/03/06 Javascript
lhgcalendar时间插件限制只能选择三个月的实现方法
2017/07/03 Javascript
mui开发中获取单选按钮、复选框的值(实例讲解)
2017/07/24 Javascript
React Native之TextInput组件解析示例
2017/08/22 Javascript
Vue 与 Vuex 的第一次接触遇到的坑
2018/08/16 Javascript
Element-UI踩坑之Pagination组件的使用
2018/10/29 Javascript
深入理解Vue keep-alive及实践总结
2019/08/21 Javascript
pytyon 带有重复的全排列
2013/08/13 Python
python八大排序算法速度实例对比
2017/12/06 Python
Flask web开发处理POST请求实现(登录案例)
2018/07/26 Python
Python实现查找字符串数组最长公共前缀示例
2019/03/27 Python
Python+OpenCv制作证件图片生成器的操作方法
2019/08/21 Python
Python while循环使用else语句代码实例
2020/02/07 Python
深入理解HTML5定时器requestAnimationFrame的使用
2018/12/12 HTML / CSS
html5写一个BUI折叠菜单插件的实现方法
2019/09/11 HTML / CSS
html5的pushstate以及监听浏览器返回事件的实现
2020/08/11 HTML / CSS
澳大利亚先进的皮肤和激光诊所购物网站:Soho Skincare
2018/10/15 全球购物
个人自荐信
2013/12/05 职场文书
药剂专业自荐信范文
2014/04/16 职场文书
国际贸易专业自荐信
2014/06/10 职场文书
忠诚奉献演讲稿
2014/09/12 职场文书
办公室行政主管岗位职责
2015/04/09 职场文书
中学语文教学反思
2016/02/16 职场文书
《蓝鲸的眼睛》读后感5篇
2020/01/15 职场文书
go语言中GOPATH GOROOT的作用和设置方式
2021/05/05 Golang
vue2实现provide inject传递响应式
2021/05/21 Vue.js
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
2021/08/23 MySQL