Aruco标签定位、测距、三维位置估算 opencv应用

3 篇文章 4 订阅
3 篇文章 0 订阅
该代码示例展示了如何使用OpenCV库进行aruco标记的相机标定,通过读取相机标定参数文件校正图像畸变,并进行三维空间中的标记定位。aruco.detectMarkers()用于检测标记,estimatePoseSingleMarkers()计算标记的旋转和平移向量,最终在图像上绘制出标记及其坐标轴。
摘要由CSDN通过智能技术生成

 

 准备:

+ aruco标签6*6

+ 相机标定文件(参考我的上篇文章)

+ 摄像头

+ 摄像头要一开始对准aruco标签才开始运行

import numpy as np
import time
import cv2
import cv2.aruco as aruco
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import yaml
import warnings
warnings.filterwarnings("ignore")
cv2.namedWindow('imgage', cv2.WINDOW_FREERATIO)



###加载标定参数yaml
###加载文件路径###
file_path = ("./4k标定参数.yaml")
# file_path = ("/home/pi/PycharmProjects/pythonProject/opencv_test/变焦相机标定参数.yaml")
###加载文件路径###

with open(file_path, "r") as file:
    parameter = yaml.load(file.read(), Loader=yaml.Loader)
    mtx = parameter['camera_matrix']
    dist = parameter['dist_coeff']
    camera_u = parameter['camera_u']
    camera_v = parameter['camera_v']
    mtx = np.array(mtx)
    dist = np.array(dist)



#打开摄像头
ID = 0
while (1):

    cap = cv2.VideoCapture(ID)
    ret, frame = cap.read()
    if ret == False:
        ID += 1
    elif ID >= 10:
        break
    else:
        #print(ID)
        break

font = cv2.FONT_HERSHEY_SIMPLEX  # font for displaying text (below)
flag = cap.isOpened()
cap.set(3, 3840)
cap.set(4, 2160)
cap.set(6, cv2.VideoWriter.fourcc(*'MJPG'))

plt.ion()
#画三维图

fig = plt.figure()
ax = fig.gca(projection="3d")


    #print(mtx, dist, camera_u, camera_v)
while 1:

    ret, img = cap.read()
    frame = img
    h1, w1 = frame.shape[:2]
    newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (h1, w1), 0, (h1, w1))
    dst1 = cv2.undistort(frame, mtx, dist, None, newcameramtx)
    x, y, w1, h1 = roi
    dst1 = dst1[y:y + h1, x:x + w1]
    frame1 = dst1

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    aruco_dict = aruco.Dictionary_get(aruco.DICT_6X6_1000)
    parameters = aruco.DetectorParameters_create()
    dst1 = cv2.undistort(frame, mtx, dist, None, newcameramtx)
    #保存图像
    # cv2.imwrite("./frame.jpg", dst1)

    '''
    detectMarkers(...)
        detectMarkers(image, dictionary[, corners[, ids[, parameters[, rejectedI
        mgPoints]]]]) -> corners, ids, rejectedImgPoints
    '''

    # 使用aruco.detectMarkers()函数可以检测到marker,返回ID和标志板的4个角点坐标
    corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, aruco_dict, parameters=parameters)

    #print(corners)
    #print(ids)
    #f是板卡的长度
    f=0.03

    #    如果找不打id
    if ids is not None:
        #计算r和t
        rvec, tvec, _ = aruco.estimatePoseSingleMarkers(corners, f, mtx, dist)
        # 估计每个标记的姿态并返回值rvet和tvec ---不同
        # from camera coeficcients
        (rvec - tvec).any()  # get rid of that nasty numpy value array error
        #print(tvec)
        #        aruco.drawAxis(frame, mtx, dist, rvec, tvec, 0.1) #绘制轴
        #        aruco.drawDetectedMarkers(frame, corners) #在标记周围画一个正方形

        for i in range(rvec.shape[0]):
            cv2.drawFrameAxes(frame, mtx, dist, rvec[i, :, :], tvec[i, :, :], 0.05)
            aruco.drawDetectedMarkers(frame, corners)

        ###### DRAW ID #####
        cv2.putText(frame, "Id: " + str(ids), (0, 64), font, 1, (0, 255, 0), 2, cv2.LINE_AA)
        # plt.imshow(frame, aspect='auto')
        cv2.imshow("imgage",frame)

        #计算两两标记间的距离并输出

        for i in range(tvec.shape[0]):
            j = i - 1
            while j >= 0:
                print('point:' + str(ids[i]) + str(ids[j]), ',dist:' + str(np.linalg.norm(tvec[i][0] - tvec[j][0])))
                j = j - 1
        #计算各个坐标到相机的距离
        for i in range(tvec.shape[0]):
            print('point:' + str(ids[i]) + ',dist:' + str(np.linalg.norm(tvec[i][0] - [0, 0, 0])))

        h1, w1 = frame.shape[:2]

        #每个标记自己的世界坐标系坐标
        #原点和四个角
        joint_world = [[0, 0, 0],
                       [f / 2, f / 2, 0],
                       [-f / 2, f / 2, 0],
                       [-f / 2, -f / 2, 0],
                       [f / 2, -f / 2, 0]]
        joint_cam_ori = []
        joint_cam_1 = []
        joint_cam_2 = []
        joint_cam_3 = []
        joint_cam_4 = []

        #循环将各个标记的世界坐标系转为相机坐标系
        #    如果找不打id
        if ids is not None:
            for i in range(rvec.shape[0]):
                R = np.zeros((3, 3), dtype=np.float64)
                cv2.Rodrigues(rvec[i, :, :], R)
                T = tvec[i][0]
                # print("R:",R)
                # print("T:",T)
                """
                世界坐标系 -> 相机坐标系: R * (pt - T):
                joint_cam = np.dot(R, (joint_world - T).T).T
                :return:
                """
                joint_world = np.asarray(joint_world)
                joint_num = len(joint_world)
                # 世界坐标系 -> 相机坐标系
                # [R|t] world coords -> camera coords
                # joint_cam = np.zeros((joint_num, 3))  # joint camera
                # for i in range(joint_num):  # joint i
                #     joint_cam[i] = np.dot(R, joint_world[i] - T)  # R * (pt - T)
                # .T is 转置, T is translation mat
                joint_cam = np.dot(R, (joint_world).T).T + T
                joint_cam_ori.append(joint_cam[0])
                joint_cam_1.append(joint_cam[1])
                joint_cam_2.append(joint_cam[2])
                joint_cam_3.append(joint_cam[3])
                joint_cam_4.append(joint_cam[4])




        xs = [0]
        ys = [0]
        zs = [0]

        for i in range(len(joint_cam_ori)):
            xs.append(joint_cam_ori[i][0])
            ys.append(joint_cam_ori[i][1] )
            zs.append(joint_cam_ori[i][2])

        for i in range(len(joint_cam_1)):
            xs.append(joint_cam_1[i][0])
            ys.append(joint_cam_1[i][1])
            zs.append(joint_cam_1[i][2])
        # '''
        for i in range(len(joint_cam_2)):
            xs.append(joint_cam_2[i][0])
            ys.append(joint_cam_2[i][1] )
            zs.append(joint_cam_2[i][2])

        for i in range(len(joint_cam_3)):
            xs.append(joint_cam_3[i][0])
            ys.append(joint_cam_3[i][1] )
            zs.append(joint_cam_3[i][2])

        for i in range(len(joint_cam_4)):
            xs.append(joint_cam_4[i][0])
            ys.append(joint_cam_4[i][1] )
            zs.append(joint_cam_4[i][2])
        # '''

        #画各个标记平面

        ax.scatter(xs, ys, zs, zdir="z", c="#00DDAA", marker="o", s=50)

        ax.set(xlabel="X", ylabel="Y", zlabel="Z")

        for i in range(len(ids)):
            j = 1 + i
            k = len(ids)
            x, y, z = np.array([[xs[j + k], ys[j + k], zs[j + k]], [xs[j + 2 * k], ys[j + 2 * k], zs[j + 2 * k]],
                                [xs[j + 3 * k], ys[j + 3 * k], zs[j + 3 * k]],
                                [xs[j + 4 * k], ys[j + 4 * k], zs[j + 4 * k]], [xs[j + k], ys[j + k], zs[j + k]],
                                [xs[j + 2 * k], ys[j + 2 * k], zs[j + 2 * k]],
                                [xs[j + 3 * k], ys[j + 3 * k], zs[j + 3 * k]],
                                [xs[j + 4 * k], ys[j + 4 * k], zs[j + 4 * k]]]).T
            ax.plot_trisurf(x, y, z)
        #画相机原点三轴
        ax.plot([0, f], [0, 0], [0, 0], label=' ', color='blue')
        ax.plot([0, 0], [0, f], [0, 0], label=' ', color='green')
        ax.plot([0, 0], [0, 0], [0, f], label=' ', color='red')

        plt.gca().set_box_aspect((3, 2, 12))  # 当x、y、z轴范围之比为3:5:2时。
        plt.pause(0.1)
        plt.cla()
        # plt.ioff()  # 关闭画图窗口Z



    else:
        ##### DRAW "NO IDS" #####
        cv2.putText(frame, "No Ids", (0, 64), font, 1, (0, 255, 0), 2, cv2.LINE_AA)


plt.clf()  # 清除之前画的图

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值