相机标定

文章目录

  • 一、相机标定简介
  • 二、实验代码
  • 三、实验结果
    • (1)实验图集:
    • (2)运行结果:
  • 四、小结

一、相机标定简介

在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型,这些几何模型参数就是相机参数。在大多数条件下这些参数必须通过实验与计算才能得到,这个求解参数的过程就称之为相机标定(或摄像机标定)。无论是在图像测量或者机器视觉应用中,相机参数的标定都是非常关键的环节,其标定结果的精度及算法的稳定性直接影响相机工作产生结果的准确性。因此,做好相机标定是做好后续工作的前提,提高标定精度是科研工作的重点所在。
本实验要求与步骤:

  1. 打印一张棋盘格A4纸张(黑白间距已知),并贴在一个平板上
  2. 针对棋盘格拍摄若干张图片(一般10-20张)
  3. 在图片中检测特征点(Harris角点)
  4. 根据角点位置信息及图像中的坐标,求解 Homographic矩阵
  5. 利用解析解估算方法计算出5个内部参数,以及 6个外部参数
  6. 根据极大似然估计策略,设计优化目标并实现 参数的refinement

二、实验代码

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

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

images = glob.glob("F:/python/pic/*.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, 6), 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,6), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值
        i+=1;
        cv2.imwrite('F:/python/pic/'+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)

三、实验结果

(1)实验图集:

原棋盘:
相机标定_第1张图片
棋盘单元格边长为2.91cm
拍摄相机:红米k20pro后置摄像机
拍摄图集:
相机标定_第2张图片

(2)运行结果:

后置摄像头的内部参数:
相机标定_第3张图片
后置摄像头的外部参数:
外部参数(旋转向量):
相机标定_第4张图片
外部参数(平移向量)
相机标定_第5张图片
相机标定_第6张图片
可视化(通过matlab的Cemara Calibrator实现):
相机标定_第7张图片
相机标定_第8张图片
相机标定_第9张图片
相机标定_第10张图片

四、小结

拍下的照片中会有一些波纹,应该是直接摄屏所产生的结果,对总体实验产生的影响不大。

你可能感兴趣的:(计算机视觉课程,python,计算机视觉,matlab)