相机标定

实验原理

张正友于1998年在论文:"A Flexible New Technique fro Camera Calibration"提出了基于单平面棋盘格的相机标定方法。该方法介于传统的标定方法和自标定方法之间,使用简单实用性强,有以下优点:

不需要额外的器材,一张打印的棋盘格即可。
标定简单,相机和标定板可以任意放置。
标定的精度高。

相机内参数

设 P=(X,Y,Z) 为场景中的一点,进行下面几个步骤:

将 P 从世界坐标系通过刚体变换变换到相机坐标系,这个变换过程使用的是相机间的相对位姿,也就是相机的外参数。
从相机坐标系,通过透视投影变换到相机的成像平面上的像点p=(x,y)。
将像点p从成像坐标系,通过缩放和平移变换到像素坐标系上点p=(μ,ν)。

我们就可以将场景中的三维点转换成图像中的二维点了。上述的变换步骤转换成具体的数学形式:
在这里插入图片描述
将矩阵K 称为相机的内参数,
在这里插入图片描述
最后可得:
在这里插入图片描述

切向畸变与径向畸变

径向畸变:这是由于透镜先天条件原因(透镜形状),成像仪中心(光学中心)的畸变为0,随着向边缘移动,畸变越厉害。
切向畸变:这是摄像机安装过程造成的,如当透镜不完全平行于图像平面的时候产生的。
在小孔模型中,一条指向在成像平面上的像仍然是直线。但是在实际拍摄的过程中,由于透镜的存在,往往将一条直线投影成了曲线,越靠近图像的边缘,这种现象越明显。透镜往往是中心对称的,使得这种不规则的畸变通常是径向对称的。主要有两大类:桶形畸变和枕形畸变。
在这里插入图片描述

实验代码

# coding=utf-8
import cv2
import numpy as np
import glob

# 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)

# 获取标定板角点的位置
objp = np.zeros((7 * 7, 3), np.float32)
objp[:, :2] = np.mgrid[0:7, 0:7].T.reshape(-1, 2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y

obj_points = []  # 存储3D点
img_points = []  # 存储2D点

images = glob.glob("C:/Users/47098/Desktop/2/*.jpg")
i=0
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    size = gray.shape[::-1]
    ret, corners = cv2.findChessboardCorners(gray, (7, 7), None)
    #print(corners)

    if ret:

        obj_points.append(objp)

        corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria)  # 在原角点的基础上寻找亚像素角点
        #print(corners2)
        if [corners2]:
            img_points.append(corners2)
        else:
            img_points.append(corners)

        cv2.drawChessboardCorners(img, (7, 7), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值
        i+=1
        cv2.imwrite('C:/Users/47098/Desktop/2/'+str(i)+'.jpg', img)
        cv2.waitKey(1500)

print(len(img_points))
cv2.destroyAllWindows()

# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)

print("ret:", ret)
print("mtx:", mtx) # 内参数矩阵
print("dist:", dist)  # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print("rvecs:", rvecs)  # 旋转向量  # 外参数
print("tvecs:", tvecs ) # 平移向量  # 外参数

print("-----------------------------------------------------")

img = cv2.imread(images[2])
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))#显示更大范围的图片(正常重映射之后会删掉一部分图像)
print (newcameramtx)
print("------------------使用undistort函数-------------------")
dst = cv2.undistort(img,mtx,dist,None,newcameramtx)
x,y,w,h = roi
dst1 = dst[y:y+h,x:x+w]
cv2.imwrite('calibresult3.jpg', dst1)
print ("方法一:dst的大小为:", dst1.shape)

实验用图

在这里插入图片描述

实验结果

相机标定
mtx为内参数矩阵,dist为畸变系数:
在这里插入图片描述
rvecs为旋转向量:
在这里插入图片描述
在这里插入图片描述
可视化:
以相机为中心
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值