使用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 相关文章推荐
初步剖析C语言编程中的结构体
Jan 16 Python
python 读写中文json的实例详解
Oct 29 Python
python re模块的高级用法详解
Jun 06 Python
Python3.5基础之变量、数据结构、条件和循环语句、break与continue语句实例详解
Apr 26 Python
pycharm 安装JPype的教程
Aug 08 Python
Python values()与itervalues()的用法详解
Nov 27 Python
python3正则模块re的使用方法详解
Feb 11 Python
Python接口自动化判断元素原理解析
Feb 24 Python
Python爬虫之Spider类用法简单介绍
Aug 04 Python
详解anaconda安装步骤
Nov 23 Python
python利用xpath爬取网上数据并存储到django模型中
Feb 26 Python
python的列表生成式,生成器和generator对象你了解吗
Mar 16 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 Http_Template_IT类库进行模板替换
2009/03/19 PHP
基于php常用正则表达式的整理汇总
2013/06/08 PHP
使用php伪造referer的方法 利用referer防止图片盗链
2014/01/20 PHP
php调用c接口无错版介绍
2014/03/11 PHP
JS 强制设为首页的代码
2009/01/31 Javascript
js中浮点型运算BUG的解决方法说明
2014/01/06 Javascript
js和jquery中循环的退出和继续下一个循环
2014/09/03 Javascript
JS基于ocanvas插件实现的简单画板效果代码(附demo源码下载)
2016/04/05 Javascript
BootStrap智能表单实战系列(四)表单布局介绍
2016/06/13 Javascript
jquery对象与DOM对象转化
2017/02/08 Javascript
js实现一键复制功能
2017/03/16 Javascript
jquery实现简单实用的轮播器
2017/05/23 jQuery
实时监控input框,实现输入框与下拉框联动的实例
2018/01/23 Javascript
用ES6写全屏滚动插件的示例代码
2018/05/02 Javascript
浅谈angular2子组件的事件传递(任意组件事件传递)
2018/09/30 Javascript
微信小程序版本自动更新的方法
2019/06/14 Javascript
基于纯JS实现多张图片的懒加载Lazy过程解析
2019/10/14 Javascript
JS正则表达式常见函数与用法小结
2020/04/13 Javascript
python数据结构之二叉树的遍历实例
2014/04/29 Python
Python比较两个图片相似度的方法
2015/03/13 Python
Python实现简单拆分PDF文件的方法
2015/07/30 Python
python jieba分词并统计词频后输出结果到Excel和txt文档方法
2018/02/11 Python
Python利用递归实现文件的复制方法
2018/10/27 Python
python计算两个矩形框重合百分比的实例
2018/11/07 Python
Python 实现OpenCV格式和PIL.Image格式互转
2020/01/09 Python
检测tensorflow是否使用gpu进行计算的方式
2020/02/03 Python
Django DRF路由与扩展功能的实现
2020/06/03 Python
浅谈Python 参数与变量
2020/06/20 Python
Python是怎样处理json模块的
2020/07/16 Python
卡塔尔航空官方网站:Qatar Airways
2017/02/08 全球购物
服装设计专业毕业生推荐信
2013/11/09 职场文书
上班离岗检讨书
2014/01/27 职场文书
有创意的广告词
2014/03/18 职场文书
旅游文化节策划方案
2014/06/06 职场文书
教师批评与自我批评发言稿
2014/10/15 职场文书
Python OpenCV实现图形检测示例详解
2022/04/08 Python