包括矩阵处理和图像处理的两个基本库

2.相机参数设置

由于本人太穷,根本搞不起较好的双目相机,于是借用opencv自带的图片。安装opencv后,在opencv\sources\samples\data下,有官方自带的图片,包括左右相机01-14(没有10)共26张双目相机照片,就以他们为例。

打开matlab进行双目相机标定(或者用opencv进行标定),由于未知标定板大小,据官方文件,其标定板可能是10mm*10mm(因为他默认大小参数是1.0,所以我猜是10mm,如有错误请大佬指出;其次,标定板大小只影响旋转和平移矩阵,对内参没影响)标定结果如下:

# 左/右相机内参数、旋转、平移矩阵
leftIntrinsic = np.array([[533.9634, 0, 342.6315],
                          [0, 533.9448, 234.3696],
                          [0, 0, 1]])
leftRotation = np.array([[1, 0, 0],
                         [0, 1, 0],
                         [0, 0, 1]])
leftTranslation = np.array([[0],
                            [0]])
rightIntrinsic = np.array([[537.6219, 0, 326.7537],
                           [0, 537.2332, 250.4047],
                           [0, 0, 1]])
rightRotation = np.array([[1, -0.0033, -0.0055],
                          [0.0033, 1, 0.0094],
                          [0.0054, -0.0094, 0.9999]])
rightTranslation = np.array([[-33.2347],
                             [0.4254],
                             [0.0085]])

matlab中,我只设置了三参数模型,标定板大小为10mm,其他默认,点击Calibrate。matlab操作不多介绍。

以左相片建立空间坐标系,所以左相机旋转和平移矩阵为单位矩阵和零矩阵。右相机的旋转和平移矩阵使用两相机间的旋转和平移矩阵。

3.函数编写

# 函数参数为左右相片同名点的像素坐标,获取方式后面介绍
# lx,ly为左相机某点像素坐标,rx,ry为右相机对应点像素坐标
def uvToXYZ(lx, ly, rx, ry):
    mLeft = np.hstack([leftRotation, leftTranslation])
    mLeftM = np.dot(leftIntrinsic, mLeft)
    mRight = np.hstack([rightRotation, rightTranslation])
    mRightM = np.dot(rightIntrinsic, mRight)
    A = np.zeros(shape=(4, 3))
    for i in range(0, 3):
        A[0][i] = lx * mLeftM[2, i] - mLeftM[0][i]
    for i in range(0, 3):
        A[1][i] = ly * mLeftM[2][i] - mLeftM[1][i]
    for i in range(0, 3):
        A[2][i] = rx * mRightM[2][i] - mRightM[0][i]
    for i in range(0, 3):
        A[3][i] = ry * mRightM[2][i] - mRightM[1][i]
    B = np.zeros(shape=(4, 1))
    for i in range(0, 2):
        B[i][0] = mLeftM[i][3] - lx * mLeftM[2][3]
    for i in range(2, 4):
        B[i][0] = mRightM[i - 2][3] - rx * mRightM[2][3]
    XYZ = np.zeros(shape=(3, 1))
    # 根据大佬的方法,采用最小二乘法求其空间坐标
    cv2.solve(A, B, XYZ, cv2.DECOMP_SVD)
    print(XYZ)
    return XYZ

4.同名点的确定与空间坐标的检验

同名点是指左右相片对应的匹配点,在空间坐标中指的是同一个点,下面用opencv相机标定的方法输出并保存标定板上各个点的坐标。

# 导入库,包括opencv和openpyxl(excel操作库,安装方法:pip install openpyxl)
import cv2
import openpyxl
import os
# 两张图片位置,这里选择left01和right01两张,位置自行更改
img1 = cv2.imread('D:/SA/2021.3/6.1/l/left01.jpg')
img2 = cv2.imread('D:/SA/2021.3/6.1/r/right01.jpg')
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 标定板角点检测
ret1, corners1 = cv2.findChessboardCorners(gray1, (6, 9), None)
ret2, corners2 = cv2.findChessboardCorners(gray2, (6, 9), None)
# 亚像素角点检测,使其角点精度更高(反正我觉得没高多少)
corners11 = cv2.cornerSubPix(gray1, corners1, (5, 5), (-1, -1), criteria)
corners21 = cv2.cornerSubPix(gray2, corners2, (5, 5), (-1, -1), criteria)
# 将数据保存到excel中,excel路径自行修改,程序自动创建,无需手动操作
excel_path = 'D:/SA/AngularPointCoordinates.xlsx'
if os.path.exists(excel_path) is False:
    workbook = openpyxl.Workbook()
    worksheet = workbook.active
    worksheet.title = 'data'
    workbook.save(excel_path)
workbook = openpyxl.load_workbook(excel_path)
sheet = workbook['data']
for i in range(0, len(corners1)):
    sheet.cell(i+1, 1, corners11[i][0][0])
    sheet.cell(i+1, 2, corners11[i][0][1])
    sheet.cell(i+1, 3, corners21[i][0][0])
    sheet.cell(i+1, 4, corners21[i][0][1])
workbook.save(excel_path)

运行程序,完成后,打开excel文件,其中有54组角点坐标,如下图所示:

其并没有进行排列,所以我们要自己判断点的位置。其中,最左上角是xy都最小的(opencv像素坐标在左上,以右为x轴、下为y轴的正方向),可以得知第六行是最左上角点坐标,前两列为左相片,后两列为右相片坐标。所以坐标为

244.4273987, 94.16474152; 127.9022751, 110.3449249

此时我们找最左上角向下10mm的那个点,位于第五行,x与其大致相同,y稍大,其坐标为:244.9057465, 126.2445526;128.8562469, 142.0508575

以上面两组数据测试,添加代码

p1 = uvToXYZ(244.4273987, 94.16474152, 127.9022751, 110.3449249)
p2 = uvToXYZ(244.9057465, 126.2445526, 128.8562469, 142.0508575)
dp = p1-p2
print(dp)

前两个为p1,p2点空间坐标(我们选的两个点),第三个为坐标差值,单位mm,除了在z方向有1.2mm误差较大外,其他方向误差较小。

5.精度分析

经多次测试,单方向最大误差小于2mm,造成这种误差可能是因为没有畸变校正。emm,下次再加上校正后在进行测试。

ps完整主代码如上,同名点确定属于另一个py文件中。

https://blog.csdn.net/qq_15947787/article/details/53366592?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162449922616780261926595%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162449922616780261926595&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-6-53366592.pc_search_result_before_js&utm_term=%E5%8F%8C%E7%9B%AE%E7%9B%B8%E6%9C%BA%E8%AE%A1%E7%AE%97%E4%B8%89%E7%BB%B4%E5%9D%90%E6%A0%87&spm=1018.2226.3001.4187

https://blog.csdn.net/weixin_43535573/article/details/88918400?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162449922616780261926595%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162449922616780261926595&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-13-88918400.pc_search_result_before_js&utm_term=%E5%8F%8C%E7%9B%AE%E7%9B%B8%E6%9C%BA%E8%AE%A1%E7%AE%97%E4%B8%89%E7%BB%B4%E5%9D%90%E6%A0%87&spm=1018.2226.3001.4187

前言:虽然计算三维坐标已经很多大佬研究过了,但是网上能用的好少啊。原理不多解释了,直接上程序。1.导入库import numpy as npimport cv2包括矩阵处理和图像处理的两个基本库2.相机参数设置由于本人太穷,根本搞不起较好的双目相机,于是借用opencv自带的图片。安装opencv后,在opencv\sources\samples\data下,有官方自带的图片,包括左右相机01-14(没有10)共26张双目相机照片,就以他们为例。打开matlab进行双目相机标定( from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D dot1 = [[0, 0, 0], [1, 1, 1], [ 2, 2, 2], [2, 2, 3], [2, 2, 4]] # 得到五个点 plt.figure() # 得到画面 ax1 = plt.axes(projection='3d') ax1.set_xlim(0, 5) # X轴,横向向右方向 ax1.set_ylim(5, 0) # Y轴,
要通过 双目 相机 获取人的 三维 坐标 ,需要 使用 三维 重建技术。通过左右两个摄像头捕捉到的图像,利用立体视觉原理 计算 出每个像素的深度信息,并进一步根据摄像头的内外参数把这些深度信息转换成 三维 空间中的点 坐标 。最后,通过对获得的 三维 点云数据进行处理和分析,即可得到人体的 三维 坐标 信息。
完成 双目 相机 标定以后,获得 双目 相机 的参数矩阵 包括左右 相机 的内参数矩阵、左右 相机 的畸变系数矩阵、右 相机 相对于左 相机 的旋转矩阵与平移矩阵 已知左右 相机 图像中的对应点 坐标 ,获取目标在 双目 视觉传感器下 三维 坐标 的流程如下: 1、将 双目 相机 标定参数整理如下: //左 相机 内参数矩阵 float leftIntrinsic[3][3] = { 3061.6936, -0.8869, 641.3042, 0, 3058.8751, 508.9555, 0, 0, 1 }; //左 相机 畸变系数 float leftDist
用scatter()散点绘制 三维 坐标 点 from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D dot1 = [[0, 0, 0], [1, 1, 1], [ 2, 2, 2], [2, 2, 3], [2, 2, 4]] # 得到五个点 plt.figure() # 得到画面 ax1 = plt.axes(projection='3d') ax1.set_xl