当前位置:   article > 正文

Python双目相机计算三维坐标(使用opencv自带图片)_双目视觉求解物体的三维坐标编程

双目视觉求解物体的三维坐标编程

前言:虽然计算三维坐标已经很多大佬研究过了,但是网上能用的好少啊。原理不多解释了,直接上程序。

1.导入库

  1. import numpy as np
  2. import cv2

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

2.相机参数设置

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

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

  1. # 左/右相机内参数、旋转、平移矩阵
  2. leftIntrinsic = np.array([[533.9634, 0, 342.6315],
  3. [0, 533.9448, 234.3696],
  4. [0, 0, 1]])
  5. leftRotation = np.array([[1, 0, 0],
  6. [0, 1, 0],
  7. [0, 0, 1]])
  8. leftTranslation = np.array([[0],
  9. [0],
  10. [0]])
  11. rightIntrinsic = np.array([[537.6219, 0, 326.7537],
  12. [0, 537.2332, 250.4047],
  13. [0, 0, 1]])
  14. rightRotation = np.array([[1, -0.0033, -0.0055],
  15. [0.0033, 1, 0.0094],
  16. [0.0054, -0.0094, 0.9999]])
  17. rightTranslation = np.array([[-33.2347],
  18. [0.4254],
  19. [0.0085]])

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

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

3.函数编写

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

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

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

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

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

  1. p1 = uvToXYZ(244.4273987, 94.16474152, 127.9022751, 110.3449249)
  2. p2 = uvToXYZ(244.9057465, 126.2445526, 128.8562469, 142.0508575)
  3. dp = p1-p2
  4. 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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/152822
推荐阅读
相关标签
  

闽ICP备14008679号