在 aruco 标记上覆盖 .obj 文件

问题描述 投票:0回答:1

我有一些样板代码来检测框架中的 aruco 标记:

import cv2

# Load the camera
cap = cv2.VideoCapture(0)

# Set the dictionary to use
dictionary = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    if not ret: continue
    detector = cv2.aruco.ArucoDetector(dictionary)

    # Detect markers
    corners, ids, _ = detector.detectMarkers(frame)

    # Draw markers
    frame = cv2.aruco.drawDetectedMarkers(frame, corners, ids)

    # Display the resulting frame
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

我希望能够导入 .obj 文件并将其覆盖在 aruco 标记上。 我不想打开任何额外的窗口,我需要一个这样的功能:

  • 它输入框架以及 aruco 标记的角点和 ID。
  • 它处理 .obj 文件并将其覆盖(像标记一样扭曲)
  • 输出帧,以便我可以 cv2.imshow() (或等效项)

有办法做到这一点吗..?

python opencv 3d aruco wavefront
1个回答
0
投票

按照 Christoph Rackwitz 的建议,我使用 OpenCV 和 Numpy 生成线框(尽管与他们建议的方式略有不同):

import cv2
import numpy as np

def read_obj(file_path):
    vertices = []
    faces = []

    with open(file_path, 'r') as file:
        for line in file:
            if line.startswith('v '):
                vertex = list(map(float, line.strip().split()[1:]))
                vertices.append(vertex)
            elif line.startswith('f '):
                face = line.strip().split()[1:]
                if '/' in face[0]:
                    face = [int(index.split('/')[0]) - 1 for index in face]
                else:
                    face = list(map(int, face))
                    face = [index - 1 for index in face]
                faces.append(face)

    return np.array(vertices), np.array(faces)

def rotate_3d(vertices, angle_x, axis_x, angle_y, axis_y, angle_z, axis_z):
    rotation_matrix_x = np.array([[1, 0, 0],
                                  [0, np.cos(np.radians(angle_x)), -np.sin(np.radians(angle_x))],
                                  [0, np.sin(np.radians(angle_x)), np.cos(np.radians(angle_x))]])

    rotation_matrix_y = np.array([[np.cos(np.radians(angle_y)), 0, np.sin(np.radians(angle_y))],
                                  [0, 1, 0],
                                  [-np.sin(np.radians(angle_y)), 0, np.cos(np.radians(angle_y))]])

    rotation_matrix_z = np.array([[np.cos(np.radians(angle_z)), -np.sin(np.radians(angle_z)), 0],
                                  [np.sin(np.radians(angle_z)), np.cos(np.radians(angle_z)), 0],
                                  [0, 0, 1]])

    rotated_vertices = vertices.copy()

    if 'x' in axis_x:
        rotated_vertices = np.dot(rotated_vertices, rotation_matrix_x.T)
    if 'y' in axis_y:
        rotated_vertices = np.dot(rotated_vertices, rotation_matrix_y.T)
    if 'z' in axis_z:
        rotated_vertices = np.dot(rotated_vertices, rotation_matrix_z.T)

    return rotated_vertices

def draw_wireframe(image, vertices, faces, r,g,b):
    for face in faces:
        pt1 = tuple(map(int, vertices[face[0]][:2]))
        pt2 = tuple(map(int, vertices[face[1]][:2]))
        pt3 = tuple(map(int, vertices[face[2]][:2]))

        cv2.line(image, pt1, pt2, (b,g,r, 255), 1)
        cv2.line(image, pt2, pt3, (b,g,r, 255), 1)
        cv2.line(image, pt3, pt1, (b,g,r, 255), 1)

def main(obj, scale_factor=100, rotation_x=0, rotation_y=0, rotation_z=0, r=255,g=255,b=255):
    vertices, faces = obj

    scaled_and_rotated_vertices = rotate_3d(vertices * scale_factor, rotation_x, 'x', rotation_y, 'y', rotation_z+180, 'z')
    translation_vector = np.array([[500, 500, 0]])
    translated_vertices = scaled_and_rotated_vertices + translation_vector

    image_size = (1000, 1000, 4)
    wireframe_image = np.zeros(image_size, dtype=np.uint8)

    draw_wireframe(wireframe_image, translated_vertices, faces, r,g,b)

    return wireframe_image

if __name__ == "__main__":
    obj = read_obj('monkey.obj')
    result_image = main(obj)

    cv2.imwrite('tmp.png', result_image)
    cv2.imshow('Wireframe', result_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
© www.soinside.com 2019 - 2024. All rights reserved.