Views
No views yet
1import os
2import json
3import torch
4from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
5from tqdm import tqdm
6import warnings
7from qwen_vl_utils import process_vision_info
8
9# Suppress a known transformers warning
10#warnings.filterwarnings("ignore", message="The models vision encoder did not receive absolute position embeddings")
11
12# --- 1. Configuration ---
13MODEL_PATH = "GabrieleGiudici/BQwen2.5-VL-3B"
14##get the file from BARD https://github.com/GabrieleGiudic/BARD/tree/master/validation/2025
15DATA_FILE = "./data2025/model_input_dataset_color_number_2025.json"
16
17OUTPUT_DIR = "./output"
18PREDICTIONS_FILE = os.path.join(OUTPUT_DIR, "action_caption.json")
19
20DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
21
22def load_model_and_processor():
23 """Loads the Qwen model and processor."""
24 print(f"?? Loading fine-tuned model from: {MODEL_PATH}")
25
26 model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
27 MODEL_PATH,
28 torch_dtype="auto",
29 device_map="auto",
30 trust_remote_code=True
31 ).eval()
32
33
34 min_pixels = 256 * 28 * 28
35 max_pixels = 448 * 28 * 28#1280 * 28 * 28
36 processor = AutoProcessor.from_pretrained(MODEL_PATH, min_pixels=min_pixels, max_pixels=max_pixels
37 )
38
39 print("? Model and processor loaded successfully.")
40 return model, processor
41
42def main():
43 """Main function to run inference and save predictions."""
44
45 os.makedirs(OUTPUT_DIR, exist_ok=True)
46
47 model, processor = load_model_and_processor()
48
49 print(f"?? Loading data from {DATA_FILE}...")
50 with open(DATA_FILE, 'r') as f:
51 dataset = json.load(f)
52
53 results = []
54 print(f"\n?? Starting inference on {len(dataset)} videos...")
55
56 fps = 3.0
57 for item in tqdm(dataset, desc="Processing videos"):
58 video_path = item['video']
59
60 human_prompt = ""
61 for conv in item['conversations']:
62 if conv['from'] == 'human':
63 human_prompt = conv['value'].replace('<video>\n', '').strip()
64 break
65
66 if not os.path.exists(video_path):
67 print(f"?? Warning: video not found at {video_path}. Skipping.")
68 continue
69
70 if not human_prompt:
71 print(f"?? Warning: No human prompt found for {video_path}. Skipping.")
72 continue
73
74
75 # Prepare model inputs
76 messages = [{"role": "user", "content": [{"type": "video", "video": video_path,"resized_height": 420,
77 "resized_width": 784,"fps": fps,}, {"type": "text", "text": human_prompt}]}]
78
79 # Preparation for inference
80 text = processor.apply_chat_template(
81 messages, tokenize=False, add_generation_prompt=True
82 )
83
84 # Process the vision info
85 image_inputs, video_inputs, video_kwargs = process_vision_info(messages, return_video_kwargs=True)
86
87
88 # Pass through processor
89 inputs = processor(
90 text=[text],
91 images=image_inputs,
92 videos=video_inputs,
93 padding=True,
94 return_tensors="pt",
95 **video_kwargs,
96 )
97
98 # Move to CUDA
99 inputs = inputs.to("cuda")
100
101
102 # Generate response
103 generated_ids = model.generate(**inputs, max_new_tokens=400, do_sample=False)
104 generated_ids = [out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]
105 response = processor.batch_decode(generated_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
106
107 results.append({
108 "image": video_path,
109 "ground_truth": item['conversations'][1]['value'],
110 "prediction": response
111 })
112
113 print(results[-1])
114
115 with open(PREDICTIONS_FILE, 'w') as f:
116 json.dump(results, f, indent=4)
117
118 print(f"\n? Inference complete. Predictions saved to {PREDICTIONS_FILE}")
119
120if __name__ == "__main__":
121 main()```
1221@article{bard,
2 title = {{BARD}: A Basketball Action Recognition Dataset for Multi-Label Classification},
3 author = {Giudici, Gabriele and Zuccolotto, Paola and Maurino, Andrea},
4 journal = {Journal of Computer Vision and Visual Understanding},
5 year = {2025},
6 doi = {10.2139/ssrn.5611722},
7 note = {Accepted for publication}
8}