File size: 6,502 Bytes
3d1f2c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import os
import sys
import json
import glob
import torch
import zipfile
import argparse
import numpy as np

from tqdm import tqdm

sys.path.insert(1, os.path.join(sys.path[0], '..'))
from utils.utils_calib import FramebyFrameCalib
from model.metrics import calc_iou_part, calc_iou_whole_with_poly, calc_reproj_error, calc_proj_error

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--root_dir", type=str, required=True)
    parser.add_argument("--split", type=str, required=True)
    parser.add_argument("--pred_file", type=str, required=True)

    args = parser.parse_args()
    return args


def get_homographies(file_paths):
    npy_files = []
    for file_path in file_paths:
        directory_path = os.path.join(os.path.join(args.root_dir, "Annotations/80_95"), file_path)
        if os.path.exists(directory_path):
            files = os.listdir(directory_path)
            npy_files.extend([os.path.join(directory_path, file) for file in files if file.endswith('.npy')])

    npy_files = sorted(npy_files)
    return npy_files


def make_file_name(file):
    file =  "TS-WorldCup/" + file.split("TS-WorldCup/")[-1]
    splits = file.split('/')
    side = splits[3]
    match = splits[4]
    image = splits[5]
    frame = image.split('_homography.npy')[0]
    return side + '-' + match + '-' + frame + '.json'


def pan_tilt_roll_to_orientation(pan, tilt, roll):
    """

    Conversion from euler angles to orientation matrix.

    :param pan:

    :param tilt:

    :param roll:

    :return: orientation matrix

    """
    Rpan = np.array([
        [np.cos(pan), -np.sin(pan), 0],
        [np.sin(pan), np.cos(pan), 0],
        [0, 0, 1]])
    Rroll = np.array([
        [np.cos(roll), -np.sin(roll), 0],
        [np.sin(roll), np.cos(roll), 0],
        [0, 0, 1]])
    Rtilt = np.array([
        [1, 0, 0],
        [0, np.cos(tilt), -np.sin(tilt)],
        [0, np.sin(tilt), np.cos(tilt)]])
    rotMat = np.dot(Rpan, np.dot(Rtilt, Rroll))
    return rotMat

def get_sn_homography(cam_params: dict, batch_size=1):
    # Extract relevant camera parameters from the dictionary
    pan_degrees = cam_params['cam_params']['pan_degrees']
    tilt_degrees = cam_params['cam_params']['tilt_degrees']
    roll_degrees = cam_params['cam_params']['roll_degrees']
    x_focal_length = cam_params['cam_params']['x_focal_length']
    y_focal_length = cam_params['cam_params']['y_focal_length']
    principal_point = np.array(cam_params['cam_params']['principal_point'])
    position_meters = np.array(cam_params['cam_params']['position_meters'])

    pan = pan_degrees * np.pi / 180.
    tilt = tilt_degrees * np.pi / 180.
    roll = roll_degrees * np.pi / 180.

    rotation = np.array([[-np.sin(pan) * np.sin(roll) * np.cos(tilt) + np.cos(pan) * np.cos(roll),
                          np.sin(pan) * np.cos(roll) + np.sin(roll) * np.cos(pan) * np.cos(tilt), np.sin(roll) * np.sin(tilt)],
                         [-np.sin(pan) * np.cos(roll) * np.cos(tilt) - np.sin(roll) * np.cos(pan),
                          -np.sin(pan) * np.sin(roll) + np.cos(pan) * np.cos(roll) * np.cos(tilt), np.sin(tilt) * np.cos(roll)],
                         [np.sin(pan) * np.sin(tilt), -np.sin(tilt) * np.cos(pan), np.cos(tilt)]], dtype='float')

    rotation = np.transpose(pan_tilt_roll_to_orientation(pan, tilt, roll))

def convert_homography_SN_to_WC14(H):
    T = np.eye(3)
    T[0, -1] = 105 / 2
    T[1, -1] = 68 / 2
    meter2yard = 1.09361
    S = np.eye(3)
    S[0, 0] = meter2yard
    S[1, 1] = meter2yard
    H_SN = S @ (T @ H)
    return H_SN

def get_homography_by_index(homography_file):
    homography = np.load(homography_file)
    homography = homography / homography[2:3, 2:3]
    return homography


if __name__ == "__main__":
    args = parse_args()

    missed = 0
    iou_part_list, iou_whole_list = [], []
    rep_err_list, proj_err_list = [], []

    with open(args.root_dir + args.split + '.txt', 'r') as file:
        # Read lines from the file and remove trailing newline characters
        seqs = [line.strip() for line in file.readlines()]

    homographies = get_homographies(seqs)
    prediction_archive = zipfile.ZipFile(args.pred_file, 'r')
    cam = FramebyFrameCalib(1280, 720, denormalize=True)

    for h_gt in tqdm(homographies):
        file_name = h_gt.split('/')[-1].split('.')[0]
        pred_name = make_file_name(h_gt)

        if pred_name not in prediction_archive.namelist():
            missed += 1
            continue

        homography_gt = get_homography_by_index(h_gt)
        final_dict = prediction_archive.read(pred_name)
        final_dict = json.loads(final_dict.decode('utf-8'))
        keypoints_dict = final_dict['kp']
        lines_dict = final_dict['lines']
        keypoints_dict = {int(key): value for key, value in keypoints_dict.items()}
        lines_dict = {int(key): value for key, value in lines_dict.items()}

        cam.update(keypoints_dict, lines_dict)
        final_dict = cam.heuristic_voting_ground(refine_lines=True)
        #homography_pred, ret = cam.get_homography_from_ground_plane(use_ransac=20, inverse=True, refine_lines=True)
        if final_dict is None:
        #if homography_pred is None:
            missed += 1
            continue
        homography_pred = final_dict["homography"]
        homography_pred = convert_homography_SN_to_WC14(homography_pred)

        iou_p = calc_iou_part(homography_pred, homography_gt)
        iou_w, _, _ = calc_iou_whole_with_poly(homography_pred, homography_gt)
        rep_err = calc_reproj_error(homography_pred, homography_gt)
        proj_err = calc_proj_error(homography_pred, homography_gt)

        iou_part_list.append(iou_p)
        iou_whole_list.append(iou_w)
        rep_err_list.append(rep_err)
        proj_err_list.append(proj_err)


    print(f'Completeness: {1-missed/len(homographies)}')
    print('IOU Part')
    print(f'mean: {np.mean(iou_part_list)} \t median: {np.median(iou_part_list)}')
    print('\nIOU Whole')
    print(f'mean: {np.mean(iou_whole_list)} \t median: {np.median(iou_whole_list)}')
    print('\nReprojection Err.')
    print(f'mean: {np.mean(rep_err_list)} \t median: {np.median(rep_err_list)}')
    print('\nProjection Err. (meters)')
    print(f'mean: {np.mean(proj_err_list) * 0.9144} \t median: {np.median(proj_err_list) * 0.9144}')