行人轨迹预测ETH数据集坐标转换

前记

最近几天对CVPR2018的一篇行人轨迹预测Social GAN进行了复现,过程中发现ETH数据集中行人的坐标已经转为了世界坐标,因此无法进行可视化,询问博主后得知要通过单应矩阵H将世界坐标反转为像素坐标,经过多次尝试成功反转,以此记录。

ETH数据集

官方链接下载的数据集分为两个文件夹seq_eth,seq_hotel以及README.txt,每个文件夹中为视频以及对应的标注信息,主要关注两个文件:obsmat.txt(标注)以及H.txt(单应性矩阵)。注:SGAN作者还对obsmat.txt进行了预处理,仅保留了[frame_id, p_id, wpx, wpy],若复现SGAN建议直接下载作者提供的链接(否则要改动代码)

转换公式

pixelpos = H^{-1} * worldpos
这个不难理解,左乘逆矩阵反转嘛,但是转换前和转换后还需要对两个坐标做一点处理。

1.worldpos为3×1列向量,[wpx, wpy, wpz],前两个元素直接读取就好,但ETH数据集没有使用wpz,标注中wpz全为0,转换前需要将wpz设置为1,即   worldpos = \begin{bmatrix}wpx \\ wpy \\ 1 \end{bmatrix}

2.求得的pixelpos同理,[px, py, pz],但需要将pz再转为1,即  pixelpos = \begin{bmatrix}px/pz \\ py/pz \\ 1 \end{bmatrix},像素坐标系中pz是无意义的,这可能也是为什么要再除以pz。

详细代码

    data = read_file('./datasets_/eth/test/obsmat.txt')
    H = np.array([
        [2.8128700e-02, 2.0091900e-03, -4.6693600e+00],
        [8.0625700e-04, 2.5195500e-02, -5.0608800e+00],
        [3.4555400e-04, 9.2512200e-05, 4.6255300e-01]
    ])
    H_inv = np.linalg.inv(H)
    frames = np.unique(data[:, 0]).tolist()  # 总帧数
    frame_data = []
    pixel_poses = []
    for frame in frames:
        frame_data.append(data[frame == data[:, 0], :])  # 重组gt, frame_data列表的每一个元素代表当前帧下所有Person的出现情况
    for frame_data_ in frame_data:
        world_pos = np.vstack((frame_data_[:, 2], frame_data_[:, 4]))
        world_pos = np.vstack((world_pos, np.ones((world_pos.shape[1]))))
        pixel_pos = np.dot(H_inv, world_pos)
        pixel_pos_ = pixel_pos[:2, :] / pixel_pos[2:, :]
        pixel_poses.append(pixel_pos_)

其中read_file为SGAN作者提供的方法,稍做了一点修改(标注文件不一致的问题)

完整可视化代码

import numpy as np
import cv2


def read_file(_path, delim='\t'):
    data = []
    if delim == 'tab':
        delim = '\t'
    elif delim == 'space':
        delim = ' '
    delim = ' '
    with open(_path, 'r') as f:
        for line in f:
            line = line.strip().split(delim)
            line = [i for i in line if not i == '']
            line = [float(i) for i in line]
            data.append(line)
    return np.asarray(data)


if __name__ == '__main__':
    data = read_file('./datasets_/eth/test/obsmat.txt')
    H = np.array([
        [2.8128700e-02, 2.0091900e-03, -4.6693600e+00],
        [8.0625700e-04, 2.5195500e-02, -5.0608800e+00],
        [3.4555400e-04, 9.2512200e-05, 4.6255300e-01]
    ])
    H_inv = np.linalg.inv(H)
    frames = np.unique(data[:, 0]).tolist()  # 总帧数
    frame_data = []
    pixel_poses = []
    for frame in frames:
        frame_data.append(data[frame == data[:, 0], :])  # 重组gt, frame_data列表的每一个元素代表当前帧下所有Person的出现情况
    for frame_data_ in frame_data:
        world_pos = np.vstack((frame_data_[:, 2], frame_data_[:, 4]))
        world_pos = np.vstack((world_pos, np.ones((world_pos.shape[1]))))
        pixel_pos = np.dot(H_inv, world_pos)
        pixel_pos_ = pixel_pos[:2, :] / pixel_pos[2:, :]
        pixel_poses.append(pixel_pos_)

    video = cv2.VideoCapture(r'D:\yjy\PycharmProjects\sgan-master\ewap_dataset\seq_eth\seq_eth.avi')
    k = 0
    index = 0
    while True:
        _, frame = video.read()
        if frame is None:
            break
        img = frame.copy()
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        if k == frames[index]:
            positions = pixel_poses[index]
            positions = np.transpose(positions)
            for p in positions:
                cy, cx = np.int32(p)
                cv2.rectangle(img, (cx - 10, cy - 20), (cx + 10, cy + 20), (255, 255, 255), thickness=2)
            index = index + 1
            cv2.imwrite('./imgs/{}.jpg'.format(k), img)
        cv2.imshow('video', img)
        cv2.waitKey(10)
        k = k + 1

结语

本身方向并不是轨迹预测,机缘巧合下找到SGAN并进行复现,并且发现该方向相关资料较少,可能这个反转操作对大佬来说确是小菜一碟,在此献丑还望大家海涵,欢迎学术交流。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年12月6日
下一篇 2023年12月6日

相关推荐