Download evaluate.py from anthony01/LumiSign: direct link, hf CLI and curl.
- Browser
- Download file 5.1 kB
-
https://huggingface.co/spaces/anthony01/LumiSign/resolve/main/evaluate.py
- Command line
-
hf download hf://spaces/anthony01/LumiSign/evaluate.py
-
curl -L -o evaluate.py https://huggingface.co/spaces/anthony01/LumiSign/resolve/main/evaluate.py
5.1 kB
| import os | |
| import glob | |
| import argparse | |
| import json | |
| import numpy as np | |
| import pandas as pd | |
| from tqdm import tqdm | |
| import torch | |
| import torch.nn as nn | |
| from torch.utils import data | |
| from generate_keypoints import process_video | |
| from models import Transformer | |
| from configs import TransformerConfig | |
| from utils import load_json, load_label_map | |
| import shutil | |
| parser = argparse.ArgumentParser(description="Evaluate function") | |
| parser.add_argument("--data_dir", required=True, help="data directory") | |
| args = parser.parse_args() | |
| class KeypointsDataset(data.Dataset): | |
| def __init__( | |
| self, | |
| keypoints_dir, | |
| max_frame_len=200, | |
| frame_length=1080, | |
| frame_width=1920, | |
| ): | |
| self.files = sorted(glob.glob(os.path.join(keypoints_dir, "*.json"))) | |
| self.max_frame_len = max_frame_len | |
| self.frame_length = frame_length | |
| self.frame_width = frame_width | |
| def interpolate(self, arr): | |
| arr_x = arr[:, :, 0] | |
| arr_x = pd.DataFrame(arr_x) | |
| arr_x = arr_x.interpolate(method="linear", limit_direction="both").to_numpy() | |
| arr_y = arr[:, :, 1] | |
| arr_y = pd.DataFrame(arr_y) | |
| arr_y = arr_y.interpolate(method="linear", limit_direction="both").to_numpy() | |
| if np.count_nonzero(~np.isnan(arr_x)) == 0: | |
| arr_x = np.zeros(arr_x.shape) | |
| if np.count_nonzero(~np.isnan(arr_y)) == 0: | |
| arr_y = np.zeros(arr_y.shape) | |
| arr_x = arr_x * self.frame_width | |
| arr_y = arr_y * self.frame_length | |
| return np.stack([arr_x, arr_y], axis=-1) | |
| def combine_xy(self, x, y): | |
| x, y = np.array(x), np.array(y) | |
| _, length = x.shape | |
| x = x.reshape((-1, length, 1)) | |
| y = y.reshape((-1, length, 1)) | |
| return np.concatenate((x, y), -1).astype(np.float32) | |
| def __getitem__(self, idx): | |
| file_path = self.files[idx] | |
| row = pd.read_json(file_path, typ="series") | |
| label = row.label | |
| label = "".join([i for i in label if i.isalpha()]).lower() | |
| pose = self.combine_xy(row.pose_x, row.pose_y) | |
| h1 = self.combine_xy(row.hand1_x, row.hand1_y) | |
| h2 = self.combine_xy(row.hand2_x, row.hand2_y) | |
| pose = self.interpolate(pose) | |
| h1 = self.interpolate(h1) | |
| h2 = self.interpolate(h2) | |
| df = pd.DataFrame.from_dict( | |
| { | |
| "uid": row.uid, | |
| "pose": pose.tolist(), | |
| "hand1": h1.tolist(), | |
| "hand2": h2.tolist(), | |
| "label": label, | |
| } | |
| ) | |
| pose = ( | |
| np.array(list(map(np.array, df.pose.values))) | |
| .reshape(-1, 50) | |
| .astype(np.float32) | |
| ) | |
| h1 = ( | |
| np.array(list(map(np.array, df.hand1.values))) | |
| .reshape(-1, 42) | |
| .astype(np.float32) | |
| ) | |
| h2 = ( | |
| np.array(list(map(np.array, df.hand2.values))) | |
| .reshape(-1, 42) | |
| .astype(np.float32) | |
| ) | |
| final_data = np.concatenate((pose, h1, h2), -1) | |
| final_data = np.pad( | |
| final_data, | |
| ((0, self.max_frame_len - final_data.shape[0]), (0, 0)), | |
| "constant", | |
| ) | |
| return { | |
| "uid": row.uid, | |
| "data": torch.FloatTensor(final_data), | |
| } | |
| def __len__(self): | |
| return len(self.files) | |
| def inference(dataloader, model, device, label_map): | |
| model.eval() | |
| predictions = [] | |
| for batch in tqdm(dataloader, desc="Eval"): | |
| input_data = batch["data"].to(device) | |
| output = model(input_data).detach().cpu() | |
| output = torch.argmax(torch.softmax(output, dim=-1), dim=-1).numpy() | |
| predictions.append({"uid": batch["uid"][0], "predicted_label": label_map[output[0]]}) | |
| return predictions | |
| video_paths = glob.glob(os.path.join(args.data_dir, "*")) | |
| save_dir = "keypoints_dir" | |
| if os.path.isdir(save_dir): | |
| shutil.rmtree(save_dir) | |
| os.mkdir(save_dir) | |
| for path in tqdm(video_paths, desc="Processing Videos"): | |
| process_video(path, save_dir) | |
| label_map = load_label_map("include") | |
| dataset = KeypointsDataset( | |
| keypoints_dir=save_dir, | |
| max_frame_len=169, | |
| ) | |
| dataloader = data.DataLoader( | |
| dataset, | |
| batch_size=1, | |
| shuffle=False, | |
| num_workers=4, | |
| pin_memory=True, | |
| ) | |
| label_map = dict(zip(label_map.values(), label_map.keys())) | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| config = TransformerConfig(size="large", max_position_embeddings=256) | |
| model = Transformer(config=config, n_classes=263) | |
| model = model.to(device) | |
| pretrained_model_name = "include_no_cnn_transformer_large.pth" | |
| pretrained_model_links = load_json("pretrained_links.json") | |
| if not os.path.isfile(pretrained_model_name): | |
| link = pretrained_model_links[pretrained_model_name] | |
| torch.hub.download_url_to_file(link, pretrained_model_name, progress=True) | |
| ckpt = torch.load(pretrained_model_name, weights_only=False) | |
| model.load_state_dict(ckpt["model"]) | |
| print("### Model loaded ###") | |
| preds = inference(dataloader, model, device, label_map) | |
| print(json.dumps(preds, indent=2)) | |