一 、相机标定代码实现

需要更改以下几处:

1、棋盘格标定板的x轴与y轴对应交点个数,代码中是11 * 8

2、需要标定图片的所在路径

3、保存标定图片结果的所在路径

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

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

images = glob.glob(r"图片所在路径/*.bmp")

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, (11, 8), 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, (11, 8), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值
        i+=1
        cv2.imwrite('图片所在路径/result'+str(i)+'.bmp', 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 ) # 平移向量  # 外参数

*标定的图片最好是16张以上

在标定结果中:

1、ret是重投影误差,误差值越小,结果越准确,尽量低于0.5,低于0.1时最佳

2、mtx是内参数矩阵K

结果演示如图:

python 游标执行插入脚本后返回 python 游标卡尺_python 游标执行插入脚本后返回

 

二、测距

        1、通过相机标定可获得相机的内参数矩阵K

                  fx  s   x0
         K =    0   fy  y0
                   0   0   1

fx,fy为焦距,一般情况下二者相等,x0、y0为主点坐标(相对于成像平面),s为坐标轴倾斜参数,理想为0

        2、有以下几个参数:

D

W 或者 被测物体的高度H

Pw 或者 照片中被测物体的高度Ph

        (4) 相机的焦距F(在内参数矩阵中得到焦距fxfy)

有测距公式:D = (W * fx) / Pw        或者        D = (H * fy) / Ph

当fx不等于fy时,可能是标定的照片拍摄不佳,或者是相机ccd结构的原因(x和y方向的像元尺寸有时候不一样),此时需要将fx与fy都带入计算距离D

示例:

(此处注意单位统一)

fx = 1.21066765e+03  #焦距x
fy = 1.21112300e+03  #焦距y

w = 9   #棋盘宽9cm
h = 12  #棋盘高12cm

pw = 461    #照片中棋盘的像素宽度
ph = 605    #照片中棋盘的像素高度

d1 = (w*fx)/pw    #d1为物体距离相机的距离
d2 = (h*fy)/ph

print("result1 = ",d1,"cm")     #实际测量d = 25cm
print("result2 = ",d2,"cm")

结果:

result1 =  23.635594034707157 cm
result2 =  24.02227438016529 cm

得到的result2更接近实际距离值