【理论+程序】利用张正友标定法,使用Opencv-Python3进行摄像机标定

要注意在输入棋盘格规格的时候,输入的是宽和高方向的角点个数,而不是棋盘格的数量。

可直接运行的代码:

"""
根据OpenCV-Python Tutorial修改的相机标定程序
OpenCV-Python Tutorial Camera Calibration link:
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html#calibration
中文教程链接:
http://woshicver.com/Eighth/7_1_%E7%9B%B8%E6%9C%BA%E6%A0%A1%E5%87%86/
"""

import numpy as np
import cv2
import glob

# 棋盘规格:宽高方向角点个数
w_corner = 11
h_corner = 11

# 角点精准化迭代过程的终止条件
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 世界坐标,如 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((w_corner*h_corner,3), np.float32)
objp[:,:2] = np.mgrid[0:w_corner,0:h_corner].T.reshape(-1,2)

# 用于存储所有图像的世界坐标点和图像坐标点
objpoints = []  # 3d point in real world space
imgpoints = []  # 2d points in image plane.

images = glob.glob('data/images/*.jpg')

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # 寻找棋盘角点
    ret, corners = cv2.findChessboardCorners(gray, (11,11),None)

    # 如果找到,则添加世界坐标点、细化后的图像坐标点
    if ret == True:
        objpoints.append(objp)
        # 亚像素级角点检测(细化)
        corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        imgpoints.append(corners2)

        # 进行可视化,绘制并显示角点
        img = cv2.drawChessboardCorners(img, (w_corner,h_corner), corners2,ret)
        # 将图像缩小1/4,以便于显示
        img = cv2.resize(img, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_CUBIC)
        cv2.imshow('img',img)
        cv2.waitKey(500)
cv2.destroyAllWindows()

'''
经过上面的步骤得到了目标点和图像点,下面进行校准。
使用函数 cv.calibrateCamera() 返回相机内参矩阵,畸变系数,旋转矩阵和平移矢量等
其中,mtx:相机内参;dist:畸变系数;revcs:旋转矩阵;tvecs:平移矢量。
'''
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
print("相机内参mtx:\n",mtx)
print("畸变系数dist:\n",dist)
print("旋转矩阵rvecs:\n",rvecs)
print("平移矢量tvecs:\n",tvecs)

'''
显示畸变矫正效果
畸变矫正有两种方法:cv.undistort()、remapping
'''
# 读取要畸变矫正的图像
img = cv2.imread("data/images/1.jpg")
h,w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))

# 使用 cv.undistort() 方法
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
# 剪裁图像
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult1.jpg', dst)

# 使用remapping方法
mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w,h), 5)
dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
# 裁剪图像
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult2.jpg', dst)

# 打印我们要求的两个矩阵参数
# print("newcameramtx:\n",newcameramtx)
# print("dist:\n",dist)

# 重投影误差
tot_error = 0
for i in range(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
    tot_error += error

print("total error: ", tot_error/len(objpoints))

标定结果:

相机内参mtx:
 [[3.62397724e+03 0.00000000e+00 1.03555673e+03]
 [0.00000000e+00 3.60800179e+03 2.28840559e+03]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00]]
畸变系数dist:
 [[ 0.01015579 -0.00968475 -0.00359203  0.00063539 -0.09014052]]
旋转矩阵rvecs:
 [array([[0.23458067],
       [0.03609411],
       [0.01378744]]), array([[0.103319  ],
       [0.01785917],
       [0.02637166]]), array([[0.19155436],
       [0.01804893],
       [0.02577625]]), array([[0.1862171 ],
       [0.0201073 ],
       [0.10007198]]), array([[ 0.03643646],
       [ 0.10606325],
       [-1.55851812]]), array([[ 0.20738004],
       [-0.10248278],
       [ 1.55692683]]), array([[0.20488035],
       [0.05415721],
       [0.02873221]]), array([[0.17458788],
       [0.0385833 ],
       [0.02149842]]), array([[0.09554853],
       [0.05823517],
       [0.1356644 ]]), array([[ 0.12800001],
       [-0.0954735 ],
       [ 1.56990554]]), array([[ 0.12825191],
       [-0.12004171],
       [ 1.56090509]]), array([[ 0.19739751],
       [-0.17778952],
       [ 1.45885639]]), array([[0.27084852],
       [0.07155931],
       [0.32709402]]), array([[0.08927987],
       [0.01542926],
       [0.02030111]]), array([[0.19449851],
       [0.00824815],
       [0.03083676]]), array([[0.17972332],
       [0.05005703],
       [0.06841965]]), array([[ 0.15105951],
       [-0.22459034],
       [ 1.40366761]]), array([[0.18017921],
       [0.00658282],
       [0.03702818]]), array([[ 0.16652348],
       [-0.16614997],
       [ 1.56031062]])]
平移矢量tvecs:
 [array([[-4.300679  ],
       [-9.36847784],
       [22.97639231]]), array([[-4.73084382],
       [-6.2112322 ],
       [23.13301126]]), array([[ -4.58038817],
       [-10.0147383 ],
       [ 25.14218226]]), array([[-4.41402887],
       [-9.73630673],
       [24.5082232 ]]), array([[-4.90003855],
       [ 0.4437966 ],
       [23.5416314 ]]), array([[  5.10049755],
       [-10.19637765],
       [ 24.38507658]]), array([[ -5.04264751],
       [-10.13239477],
       [ 25.16396889]]), array([[ -5.15920078],
       [-12.89855307],
       [ 26.46382224]]), array([[ -4.73734106],
       [-12.11464393],
       [ 28.50105915]]), array([[  5.12128348],
       [-11.26842165],
       [ 26.59711439]]), array([[  5.16858973],
       [-10.19007255],
       [ 22.47868555]]), array([[  5.14837646],
       [-10.20699796],
       [ 24.61079007]]), array([[ -3.58050408],
       [-11.7782039 ],
       [ 26.02613586]]), array([[-4.74846329],
       [-9.70068358],
       [23.74349543]]), array([[ -4.6623531 ],
       [-10.0071674 ],
       [ 24.09164532]]), array([[-4.55941641],
       [-9.38868484],
       [24.73900225]]), array([[  4.84588293],
       [-10.6009499 ],
       [ 25.67295188]]), array([[-4.67294025],
       [-7.13850229],
       [23.33850262]]), array([[ 5.08380542],
       [-8.77305999],
       [23.97963252]])]
total error:  0.06548598288547088
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值