Python计算机视觉 照相机标定

参考博客:

  1. 标定原理:https://blog.csdn.net/honyniu/article/details/51004397
  2. 标定原理: https://blog.csdn.net/waeceo/article/details/50580607
  3. 代码实现: https://blog.csdn.net/weixin_43843780/article/details/89294131

标定照相机是指计算出该照相机的内参数。标定照相机的标准方法是,拍摄多幅平面棋盘模式的图像,然后进行处理计算。由于光线在远离透镜中心的地方比靠近中心的地方更加弯曲或是透镜质量原因,图像会产生径向畸变。所以我们需要畸变校正。可以通过相机标定校正这种镜头畸变,生成校正后的图像。

一、照相机标定原理

摄像机标定(Camera calibration)简单来说是从世界坐标系换到图像坐标系的过程,也就是求最终的投影矩阵的过程。
一般来说,标定的过程分为两个部分(参考: https://blog.csdn.net/honyniu/article/details/51004397 ):
第一步是从世界坐标系转换为相机坐标系,这一步是三维点到三维点的转换,包括 R,t(相机外参)等参数;
第二步是从相机坐标系转为图像坐标系,这一步是三维点到二维点的转换,包括 K(相机内参)等参数;
在这里插入图片描述
(图源: https://blog.csdn.net/waeceo/article/details/50580607

1.世界坐标系(Xw,Yw,Zw)至相机坐标系(Xc,Yc,Zc)
在这里插入图片描述
在这里插入图片描述

2.相机坐标系(Xc,Yc,Zc)至图像坐标系(x,y)
在这里插入图片描述
在这里插入图片描述
以上根据三角形相似原理可得。
像主点偏移:
在这里插入图片描述
内参矩阵K:
在这里插入图片描述

3.两类参数:
在这里插入图片描述

二、照相机标定实现

1.标记步骤:
1、打印一张棋盘格,把它贴在一个平面上,作为标定物。
2、通过调整标定物或摄像机的方向,为标定物拍摄一些不同方向的照片(一般10~20张)。
3、从照片中提取棋盘格角点(Harris特征)。
4、估算理想无畸变的情况下,五个内参和六个外参。
5、应用最小二乘法估算实际存在径向畸变下的畸变系数。
6、极大似然法,优化估计,提升估计精度。

2.实验代码:
(参考同学博客: https://blog.csdn.net/weixin_43843780/article/details/89294131

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((4 * 6, 3), np.float32)
objp[:, :2] = np.mgrid[0:6, 0:4].T.reshape(-1, 2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y

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

images = glob.glob("image4/*.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, (6, 4), 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, (6, 4), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值
        i+=1;
        cv2.imwrite('conimg'+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:\n", mtx) # 内参数矩阵
print("dist:\n", dist)  # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print("rvecs:\n", rvecs)  # 旋转向量  # 外参数
print("tvecs:\n", 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)

我准备的黑白棋盘格是格子数为7乘5的,内角点为6乘4,手机型号为iPhone 6s。
将它放在一个平面上不同角度拍摄10张作为实验素材。
在这里插入图片描述
运行结果如下:
角点提取结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
mtx为内参数矩阵,dist为畸变系数,rvecs为旋转向量,tvecs为平移向量。
校正前后的照片:
前:
在这里插入图片描述
后:
在这里插入图片描述
综上,iPhone 6s的后置摄像头内置参数矩阵为
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43848422/article/details/89302724