​[openCV Calibration] 相机矫正

news/2024/7/1 5:32:57

镜头变形是摄影中常见的现象,使用广角的时候更可以看的出来,失真主要有以下两种:

  • 径向畸变(radial distortion)

  • 切向畸变(tangential distortion)

径向畸变

光线经入透镜折射后会产生偏折,造成形变,而当透镜越小时形变会越明显,也就是原本的直线会出现弯曲,而离中心点越远,变化会越来越严重,广角的话常产生下图中间的形变,而长焦镜头则常是右侧的形变。

f8c672a3d6700e18b8715122d8a617a2.png 9284554d56731d8da1771b7f311e511d.png

切向畸变

主要发生在硬件瑕疵上,当镜头没有完全与成像平面对齐时,便会产生误差,有些图片会比想像中的来的更紧密。

c9398893513f36e5fd2a8367cfd08573.png 1923ccc8647014858530658bfff7bf06.png

我们需要的参数

透过上述俩个式子,我们需要找出五个系数,以及相机固有/外部参数

  • Five params

  • Intrinsic Params

  • Extrinsix Params

Five params

ff3e8f8d729f7aa2aa0083e2d86b3c06.png

Intrinsic Params

有焦距(focal length)→(fx,fy),光学中心(optical center)→(cx,cy)等信息,我们可以将它们组合成一个矩阵来去除因特定相机镜头而造成的失真。显而易见,这个matrix只需调整一次,便可应用在这个相机拍摄的不同照片上。

432c7dea3c1b1da462fe19eaae893af9.png

Extrinsix Params

外部参数则是对应于3D坐标系的转换(旋转/平移),要找到这些参数,我们需要透过一些(至少>10张)来找到相关的某个特定点的。(例如:国际象棋,利用正方形边框的顶点)。因为我们已经知道现实空间中棋盘格各点的坐标,也知道图片内的各点坐标,如此便可消除失真的影响。

让我们进入代码实作部分

现在提供Github Repository,让大家可以运行:

https://github.com/tarkers/Camera_Calibration_OpenCV

c8fe303e22fad96c1ab48d3bcd4580e0.png

先定义一下关键字:3D点叫对象点(object points),2D像点叫图像点(image points)

我们所需要的就是在图像中的棋盘中寻找有一组对象点的图像点,因为有照片,所以对我们来说是相对比较好找的。我们知道棋盘格在这几张图片内,有不同的位置及方向, 那对象点(X,Y,Z)我们又该如何找呢?

因为3维太麻烦了,我们可以将棋盘格定为XY平面(Z=0),然后让我们把摄像机放在它上面,这样我们只须找出X,Y即可。我们可以简单的标点上去

  1. 若不知道棋盘大小,那我们的基本长度就是以格子为单位:(0,0),(0,1),(0,2)……

  2. 若已知每格是M毫米,那我们也可以标为:(0,0),(0,M)(0,2M)....。

以这次实例,我们第一次实作。

openCV Func 介绍:

  • cv.findChessboardCorners()

    • https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html#ga93efa9b0aa890de240ca32b11253dd4a

  • cv.cornerSubPix

    • https://docs.opencv.org/4.x/dd/d1a/group__imgproc__feature.html#ga354e0d7c86d0d9da75de9b9701a9a87e

  • cv.calibrateCamera()

    • https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html#ga3207604e4b1a1758aa66acb6ed5aa65d

来自 OpenCV 的简单代码

将图像读入并计算2D/3D点,利用opencv的calibrateCameramatrix和distortion coefficients。这样便能修正图片了

import numpy as np
import cv2 as cv
import glob
# termination criteria
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
images = glob.glob('*.jpg')
for fname in images:
    img = cv.imread(fname)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # Find the chess board corners
    ret, corners = cv.findChessboardCorners(gray, (7,6), None)
    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)
        corners2 = cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners)
        # Draw and display the corners
        cv.drawChessboardCorners(img, (7,6), corners2, ret)
        cv.imshow('img', img)
        cv.waitKey(500)
cv.destroyAllWindows()
#calibration
ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# get undistorted image
img = cv.imread('left12.jpg')
h,  w = img.shape[:2]
newcameramtx, roi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
# undistort
dst = cv.undistort(img, mtx, dist, None, newcameramtx)
# crop the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv.imwrite('calibresult.png', dst)

结果

可以看到棋盘边缘明显弯曲的线,有被修正回来

76884e9a8dfd86cbaacb38fb6f33b99c.png

左:失真,右:失真

透过这样的介绍,相信大家对校准有更深的认识啦!我们下回见:

参考:

https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html

https://allen108108.github.io/blog/2020/02/15/%E5%BD%B1%E5%83%8F%E7%95%B8%E8%AE%8A%20Image%20Distortion/

https://learnopencv.com/camera-calibration-using-opencv/

☆ END ☆

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文。

扫描二维码添加小编↓

bc65c5725581a0d3c7adcc77dfbd2fd1.jpeg


http://lihuaxi.xjx100.cn/news/133272.html

相关文章

最大的和(冬季每日一题 2)

给定一个长度为 nnn 的正整数数列 a1,a2,…,ana_1,a_2,…,a_na1​,a2​,…,an​。 初始时,数列中的每个元素要么处于可选状态,要么处于不可选状态。 你可以选择一个长度恰好为 kkk 的区间 [i,ik−1][i,ik−1][i,ik−1],使得 ai∼aik−1a_i∼…

2021 增强式学习RL 李宏毅

到目前为止,我們講的幾乎都是 Supervised Learning、就算是我們在講 Self Supervised Learning 的時候、其实也是很类似Supervised Learning的方法,只是label不需要特別僱用人力去標記,可以自动产生。或者是我們在講 Auto-encoder 的時候、我…

async-rdma:使高性能网络应用开发更简单

王恒宇,中科院软件所基础软件实验室研究生。主要研究方向为软硬件融合,对物联网、操作系统、Serverless等方向感兴趣。DatenLord社区async-rdma项目贡献者之一,曾获嵌入式芯片与系统设计竞赛一等奖等多项国家级奖项,参与编写《ope…

第四章:存储子系统 [计算机组成原理笔记](自用)

第四章 存储子系统存储器与分类存储方式分类存储器系统的性能指标数据线与地址线的计算(重点)半导体只读存储器ROMSRAM与DRAM的区分主存储器的构建及存储结构设计(重点)动态存储器的刷新刷新和重写的区别刷新周期的安排方式校验码…

计算机网络——IPv4地址的划分

💟💟前言 ​ 友友们大家好,我是你们的小王同学😗😗 今天给大家打来的是 计算机网络——IPv4地址的划分 希望能给大家带来有用的知识 觉得小王写的不错的话麻烦动动小手 点赞👍 收藏⭐ 评论📄 小…

喜讯!神策数据荣登 2022 年度数字化保险百强榜

在 2022 首届亚太区数字化保险国际峰会(ADIS 2022)上,神策数据凭借着在保险行业数字化转型领域的多重优势,以及产品与服务侧的扎实能力,荣登“2022 年度数字化保险百强榜”!作为数字化保险产业链的重要评选…

如何找到日文文献?

大学毕业写论文,最重要的就是论文检索,检索出来的论文不仅可以作为自己论文题目、研究方向、论点论证,还可以放在自己论文里当参考文献。 中文论文和英文论文都是我们常用的论文,检索网站和方法也很好找,如是其他语种…

java计算机毕业设计国外摇滚乐队交流和周边售卖系统MyBatis+系统+LW文档+源码+调试部署

java计算机毕业设计国外摇滚乐队交流和周边售卖系统MyBatis系统LW文档源码调试部署 java计算机毕业设计国外摇滚乐队交流和周边售卖系统MyBatis系统LW文档源码调试部署本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开发软件&#xf…