sfm算法流程一般是特征点提取、特征点匹配、计算本质矩阵/基础矩阵,最后三角化。但是利用机械臂去观察周围,前后帧姿态变化参数是具有的,所以不需要通过基础矩阵获取。
即利用机械臂的信息直接进行深度估计。已知:手眼标定、相机外参(利用机械臂可获取)、两次拍摄图片目标的像素位置。求目标深度。目前从几次测试来看,效果还是可信的,具体误差没有评估。
利用的公式如下:
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- # @Time :2022/7/27 14:59
- # @Author :weiz
- # @ProjectName :robotVision3
- # @File :triangulation.py
- # @Description :
- import cv2
-
- from triangulation_data import *
- import math
-
-
- def get_M(R, t):
- """
- 获取旋转平移的矩阵
- :param R:
- :param t:
- :return:
- """
- M = [[R[0][0], R[0][1], R[0][2], t[0]],
- [R[1][0], R[1][1], R[1][2], t[1]],
- [R[2][0], R[2][1], R[2][2], t[2]]]
- return np.array(M)
-
-
-
- def get_M_homo(R, t):
- """
- 获取旋转平移的齐次矩阵
- :param R:
- :param t:
- :return:
- """
- M = [[R[0][0], R[0][1], R[0][2], t[0]],
- [R[1][0], R[1][1], R[1][2], t[1]],
- [R[2][0], R[2][1], R[2][2], t[2]],
- [0, 0, 0, 1]]
- return np.array(M)
-
-
- def get_world2point2_R_t(R_camera2gripper, t_camera2gripper, point1_gripper, point2_gripper):
- """
- 获取关键点1坐标系到关键点2坐标系的 R,t
- :param R_camera2gripper:手眼标定的R
- :param t_camera2gripper:手眼标定的t
- :param point1_gripper:视点1时刻机械臂末端的位姿[x,y,z,rx,ry,rz]
- :param point2_gripper:视点2时刻机械臂末端的位姿[x,y,z,rx,ry,rz]
- :return:
- """
- R_gripper2base_point1 = np.zeros((3, 3))
- t_gripper2base_point1 = np.array([point1_gripper[0], point1_gripper[1], point1_gripper[2]])
- cv2.Rodrigues(np.array([point1_gripper[3], point1_gripper[4], point1_gripper[5]]), R_gripper2base_point1)
-
- R_gripper2base_point2 = np.zeros((3, 3))
- t_gripper2base_point2 = np.array([point2_gripper[0], point2_gripper[1], point2_gripper[2]])
- cv2.Rodrigues(np.array([point2_gripper[3], point2_gripper[4], point2_gripper[5]]), R_gripper2base_point2)
-
- R_gripper2camera = np.linalg.inv(np.array(R_camera2gripper))
- t_gripper2camera = -np.dot(R_gripper2camera, t_camera2gripper)
-
- R_base2gripper_point2 = np.linalg.inv(np.array(R_gripper2base_point2))
- t_base2gripper_point2 = -np.dot(R_base2gripper_point2, t_gripper2base_point2)
-
- M = get_M_homo(R_camera2gripper, t_camera2gripper)
- M = np.matmul(get_M_homo(R_gripper2base_point1, t_gripper2base_point1), M)
- M = np.matmul(get_M_homo(R_base2gripper_point2, t_base2gripper_point2), M)
- M = np.matmul(get_M_homo(R_gripper2camera, t_gripper2camera), M)
-
- R_world2point2 = M[0:3, 0:3]
- t_world2point2 = np.array([M[0][3], M[1][3], M[2][3]])
- # print(M)
- # print(R_world2point2)
- # print(t_world2point2)
-
- return R_world2point2, t_world2point2, M
-
-
- def triangulation(point1, point2, ipm, R_world2point2, t_world2point2):
- """
- 三角测量:利用机械臂位姿信息直接进行三维坐标估计
- :param point1:该坐标系为世界坐标系
- :param point2:
- :param ipm:相机内参
- :param R_world2point2:
- :param t_world2point2:
- :return:
- """
- ipm = np.array(ipm)
- M1 = np.matmul(ipm, get_M(np.eye(3, 3), [0, 0, 0]))
- M2 = np.matmul(ipm, get_M(R_world2point2, t_world2point2))
- A = []
- A.append(point1[0] * M1[2] - M1[0])
- A.append(point1[1] * M1[2] - M1[1])
- A.append(point2[0] * M2[2] - M2[0])
- A.append(point2[1] * M2[2] - M2[1])
- # print(np.array(A))
- U, sigma, V = np.linalg.svd(A)
- p_1 = [V[3][0], V[3][1], V[3][2], V[3][3]]
- p_2 = [V[3][0] / V[3][3], V[3][1] / V[3][3], V[3][2] / V[3][3]]
- # print(p_1)
- # print(p_2)
-
- total_error = 0
- point1_pro, _ = cv2.projectPoints(np.array([p_2]), np.eye(3), np.array([[0.], [0.], [0.]]), ipm, None)
- point2_pro, _ = cv2.projectPoints(np.array([p_2]), R_world2point2, t_world2point2, ipm, None)
- print(point2_pro)
- total_error = total_error + cv2.norm(np.array([[point1]], dtype=np.double), point1_pro, cv2.NORM_L2) / 1.
- total_error = total_error + cv2.norm(np.array([[point1]], dtype=np.float64), point2_pro, cv2.NORM_L2) / 1.
- print(total_error)
-
- return p_2
-
-
- def triangulation_opencv(point1, point2, ipm, R_world2point2, t_world2point2):
- point1 = np.array([point1], dtype=np.float32)
- point2 = np.array([point2], dtype=np.float32)
-
- M1 = np.zeros((3, 4))
- M2 = np.zeros((3, 4))
- M1[0:3, 0:3] = np.eye(3)
- M2[0:3, 0:3] = np.float32(R_world2point2)
- M2[:, 3] = np.float32(t_world2point2)
- M1 = np.matmul(ipm, M1)
- M2 = np.matmul(ipm, M2)
- p_homo = cv2.triangulatePoints(M1, M2, point1.T, point2.T)
- p = []
- # 齐次坐标转三维坐标:前三个维度除以第四个维度
- for i in range(len(p_homo[0])):
- col = p_homo[:, i]
- col /= col[3]
- p.append([col[0], col[1], col[2]])
- return p[0]
-
-
-
-
-
- R_camera2gripper =[[-0.999266726198567, -0.016016251269208765, -0.0347777171142492],
- [-0.03487664683144269, 0.005939423009193905, 0.99937397542667],
- [-0.015799665129108013, 0.9998540908300567, -0.00649366092498505]]
- t_camera2gripper = [0.057164748537088694, 0.10581519613132581, 0.1255394553568957]
- ipm = np.array([[535.05, 0, 653.005], [0, 535.01, 386.191], [0, 0, 1]])
- if __name__ == "__main__":
- R_world2point2, t_world2point2, M = get_world2point2_R_t(R_camera2gripper, t_camera2gripper, point1_gripper, point2_gripper)
- p = triangulation(point1, point2, ipm, R_world2point2, t_world2point2)
- print(p)
-
- p = triangulation_opencv(point1, point2, ipm, R_world2point2, t_world2point2)
- print(p)
数据:
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- # @Time :2022/7/29 9:28
- # @Author :weiz
- # @ProjectName :Sfm-python-master
- # @File :triangulation_data.py
- # @Description :
- # Copyright (C) 2021-2025 Jiangxi Institute Of Intelligent Industry Technology Innovation
- import numpy as np
-
-
- point1 = [738, 389] # 0.5410932
- point1_gripper = [0.5122332451863898, 0.5128182769039566, 0.9630757531852082, -0.7115522167741687, -1.7916510038378088, 1.7013068394360287]
- point2 = [797, 374]
- point2_gripper = [0.3820852469525631, 0.5235437570806256, 0.9711089613285708, -0.7071726699555351, -1.9459688091738208, 1.7263544531858268]
-
- # point1 = [797, 374] # 0.54940385
- # point1_gripper = [0.3820852469525631, 0.5235437570806256, 0.9711089613285708, -0.7071726699555351, -1.9459688091738208, 1.7263544531858268]
- # point2 = [715, 343]
- # point2_gripper = [0.5056936674804589, 0.4650883838281726, 1.0634729391460807, -0.6999271853483486, -1.749012465435611, 1.6882826312357782]
-
- # point1 = [715, 343] # 0.64878213
- # point1_gripper = [0.5056936674804589, 0.4650883838281726, 1.0634729391460807, -0.6999271853483486, -1.749012465435611, 1.6882826312357782]
- # point2 = [733, 368]
- # point2_gripper = [0.5485518509025477, 0.5157901201998042, 0.9837568437877331, -0.6609672121210775, -1.7084733902118903, 1.7261963960916609]
-
- # point1 = [733, 368] # 0.5727386
- # point1_gripper = [0.5485518509025477, 0.5157901201998042, 0.9837568437877331, -0.6609672121210775, -1.7084733902118903, 1.7261963960916609]
- # point2 = [738, 389]
- # point2_gripper = [0.5122332451863898, 0.5128182769039566, 0.9630757531852082, -0.7115522167741687, -1.7916510038378088, 1.7013068394360287]
-
-
- def pixel_normalization(point1, point2):
- points_norm = []
- points_norm.append(point1)
- points_norm.append(point2)
- points_norm = np.array(points_norm)
- points_norm = (points_norm - np.mean(points_norm)) / np.std(points_norm)
- return points_norm[0], points_norm[1]
-
-
- if __name__ == "__main__":
- p1, p2 = pixel_normalization(point1, point2)
- print(p1)
- print(p2)