使用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中xrange和range的区别
May 13 Python
python 实现在txt指定行追加文本的方法
Apr 29 Python
Linux下python3.7.0安装教程
Jul 30 Python
Django 路由控制的实现代码
Nov 08 Python
Django中的用户身份验证示例详解
Aug 07 Python
wxPython实现绘图小例子
Nov 19 Python
Pandas实现DataFrame按行求百分数(比例数)
Dec 27 Python
python生成大写32位uuid代码
Mar 03 Python
Python任务调度利器之APScheduler详解
Apr 02 Python
基于python纯函数实现井字棋游戏
May 27 Python
使用python库xlsxwriter库来输出各种xlsx文件的示例
Sep 01 Python
Python编程中内置的NotImplemented类型的用法
Mar 23 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
教你如何把一篇文章按要求分段
2006/10/09 PHP
ubuntu下配置nginx+php+mysql详解
2015/09/10 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
2020/05/15 PHP
超级简单的图片防盗(HTML),好用
2007/04/08 Javascript
基于JQuery的模拟苹果桌面Dock效果(稳定版)
2012/10/15 Javascript
node.js下LDAP查询实例分享
2015/09/30 Javascript
你一定会收藏的Nodejs代码片段
2016/02/04 NodeJs
实例讲解JavaScript中的this指向错误解决方法
2016/06/13 Javascript
如何用js实现鼠标向上滚动时浮动导航
2016/07/18 Javascript
JS如何设置cookie有效期为当天24点并弹出欢迎登陆界面
2016/08/04 Javascript
浅谈JS的基础类型与引用类型
2016/09/13 Javascript
jQuery插件ContextMenu自定义图标
2017/03/15 Javascript
使用vue.js编写蓝色拼图小游戏
2017/03/17 Javascript
javaScript中"=="和"==="的区别详解
2018/03/16 Javascript
Vue的props父传子的示例代码
2020/05/20 Javascript
Python使用scrapy抓取网站sitemap信息的方法
2015/04/08 Python
pandas 将索引值相加的方法
2018/11/15 Python
浅谈Scrapy网络爬虫框架的工作原理和数据采集
2019/02/07 Python
python matplotlib实现双Y轴的实例
2019/02/12 Python
python 使用plt画图,去除图片四周的白边方法
2019/07/09 Python
浅谈Django+Gunicorn+Nginx部署之路
2019/09/11 Python
Python如何实现小程序 无限求和平均
2020/02/18 Python
Python爬虫实例——爬取美团美食数据
2020/07/15 Python
详解python变量与数据类型
2020/08/25 Python
python3.9实现pyinstaller打包python文件成exe
2020/12/13 Python
python实现按日期归档文件
2021/01/30 Python
对Pytorch 中的contiguous理解说明
2021/03/03 Python
美国快时尚彩妆品牌:Winky Lux(透明花瓣润唇膏)
2018/11/06 全球购物
OSPREY LONDON官网:英国本土皮具品牌
2019/05/31 全球购物
运动会800米加油稿
2014/02/22 职场文书
护士医德考评自我评价
2015/03/03 职场文书
夏洛特的网观后感
2015/06/15 职场文书
上班旷工检讨书
2015/08/15 职场文书
Python中glob库实现文件名的匹配
2021/06/18 Python
mysql分表之后如何平滑上线详解
2021/11/01 MySQL
使用refresh_token实现无感刷新页面
2022/04/26 Javascript