55import os
66import json
77from tqdm import tqdm
8- import shortuuid
98
109from llava .constants import IMAGE_TOKEN_INDEX , DEFAULT_IMAGE_TOKEN , DEFAULT_IM_START_TOKEN , DEFAULT_IM_END_TOKEN
1110from llava .conversation import conv_templates , SeparatorStyle
11+ from llava import conversation as conversation_lib
1212from llava .model .builder import load_pretrained_model
1313from llava .data .dataset import LazySupervisedDataset
1414from llava .utils import disable_torch_init
1515from llava .mm_utils import tokenizer_image_token , get_model_name_from_path , KeywordsStoppingCriteria
16- from llava .mm_utils import process_images
16+ from llava .mm_utils import process_images , process_image
1717
18- from PIL import Image
1918import math
20- import numpy as np
19+ import signal
2120
22- from torchvision .transforms import Resize
23- from pytorchvideo .data .encoded_video import EncodedVideo
21+ LABEL_PATHS = {
22+ "pexels" : "/home/yukangc/VILA-Benchmark/label/pexels.json" ,
23+ "robotics" : "/home/yukangc/VILA-Benchmark/label/robotics.json" ,
24+ "av" : "/home/yukangc/VILA-Benchmark/label/av.json" ,
25+ "long" : "/home/yukangc/VILA-Benchmark/label/long.json" ,
26+ }
2427
25- import signal
28+ VIDEO_DIR = {
29+ "pexels" : "/home/yukangc/VILA-Benchmark/data/pexels" ,
30+ "robotics" : "/home/yukangc/VILA-Benchmark/data/robotics" ,
31+ "av" : "/home/yukangc/VILA-Benchmark/data/av" ,
32+ "long" : "/home/yukangc/VILA-Benchmark/data/long" ,
33+ }
2634
2735# This function will be called when the timeout is reached
2836def handler (signum , frame ):
@@ -42,13 +50,30 @@ def get_chunk(lst, n, k):
4250
4351
4452def get_model_output (model , image_processor , tokenizer , video_path , qs , args ):
53+ conversation_lib .default_conversation = conversation_lib .conv_templates [
54+ args .conv_mode
55+ ]
56+ if hasattr (model .config , 'num_video_frames' ) and model .config .num_video_frames is not None :
57+ num_video_frames = model .config .num_video_frames
58+ else :
59+ num_video_frames = 8
4560
46- num_video_frames = model .config .num_video_frames
47- print ( "num_video_frames" , num_video_frames )
48- images , video_loading_succeed = LazySupervisedDataset . _load_video ( video_path , num_video_frames , data_args = args )
49- image_tensor = process_images ( images , image_processor , model . config )
61+ if hasattr ( model . config , 'fps' ) and model .config .fps is not None :
62+ fps = model . config . fps
63+ else :
64+ fps = 0.0
5065
51- qs = '<image>\n ' * num_video_frames + qs
66+ # print(fps)
67+ images , frames_loaded = LazySupervisedDataset ._load_video (video_path , num_video_frames , fps , args )
68+ # image_tensor = process_images(images, image_processor, model.config)
69+ image_tensor = torch .stack (
70+ [process_image (image , args , None ) for image in images ]
71+ )
72+ num_frames_loaded_successfully = len (images )
73+ # print(f"Number of frames loaded successfully: {num_frames_loaded_successfully}")
74+ qs = qs .replace ("<image>\n " , "" ).replace ("\n <image>" , "" ).replace ("<image>" , "" )
75+ qs = qs .replace ("<video>\n " , "" ).replace ("\n <video>" , "" ).replace ("<video>" , "" )
76+ qs = '<image>\n ' * num_frames_loaded_successfully + qs
5277
5378 conv = conv_templates [args .conv_mode ].copy ()
5479 conv .append_message (conv .roles [0 ], qs )
@@ -89,99 +114,93 @@ def get_model_output(model, image_processor, tokenizer, video_path, qs, args):
89114 outputs = outputs .strip ()
90115 return outputs
91116
92- def parse_caption_template (template_type ):
93- if "bin" in template_type :
94- short_bin = template_type .split ("_" )[1 ]
95- long_bin = template_type .split ("_" )[2 ]
96- short_question = "Elaborate on the visual and narrative elements of the video in detail."
97- long_question = f"Summarize the visual content of the following video. Please write the caption with no more than { long_bin } words.\n <video>"
98- else :
99- raise ValueError (f"Invalid template type: { template_type } " )
100-
101- return short_question , long_question
102-
103117def eval_model (args ):
104118 # Model
105119 disable_torch_init ()
106120
107121 # List video files
108122 video_formats = ['.mp4' , '.avi' , '.mov' , '.mkv' ]
109- video_files = os .listdir (args .video_dir )
123+ if not args .eval_type in ["pexels" , "robotics" , "av" , "long" ]:
124+ raise ValueError ("Unsupported eval type %s" % args .eval_type )
125+
126+ video_dir = VIDEO_DIR [args .eval_type ]
127+ video_files = os .listdir (video_dir )
110128 video_files = [f for f in video_files if os .path .splitext (f )[1 ] in video_formats ]
111- short_q , long_q = parse_caption_template ( args . prompt_template )
129+ short_q = "Elaborate on the visual and narrative elements of the video in detail."
112130 gt_questions = []
113- questions = json .load (open ("/lustre/fs2/portfolios/nvr/users/yukangc/datasets/Video-Benchmark-Label-0607.json" ))
114- question_dict = {}
115- for item in questions :
116- question_dict [item ['video_name' ]+ ".mp4" ] = item ['Q' ]
117131 for i , video_name in enumerate (video_files ):
118132 gt_questions .append (
119133 {
120134 'video_name' : video_name ,
121- 'short_q' : question_dict [video_name ], #short_q,
122- 'long_q' : long_q ,
135+ 'short_q' : short_q ,
123136 }
124137 )
125138
126139 # Create the output directory if it doesn't exist
127140
128-
129141 args .output_dir = os .path .expanduser (args .output_dir )
130142 if not os .path .exists (args .output_dir ):
131143 os .makedirs (args .output_dir )
132144 print (f"Output directory: { args .output_dir } " )
133- args .video_dir = os .path .expanduser (args .video_dir )
134- print (f"Video directory: { args .video_dir } " )
135- short_caption_file = os .path .join (args .output_dir , f"detailed_captions.txt" )
136- short_caption_file = open (short_caption_file , "w" )
137- long_caption_file = os .path .join (args .output_dir , f"video_captions.txt" )
138- long_caption_file = open (long_caption_file , "w" )
139-
140- # List to store the output results
141- output_list = []
142-
145+ video_dir = os .path .expanduser (video_dir )
146+ print (f"Video directory: { video_dir } " )
143147
144148 model_path = os .path .expanduser (args .model_path )
145149 model_name = get_model_name_from_path (model_path )
146150 tokenizer , model , image_processor , context_len = load_pretrained_model (model_path , model_name , args .model_base )
147151 args .image_processor = image_processor
148152
153+
154+ if hasattr (model .config , 'image_aspect_ratio' ) and model .config .image_aspect_ratio is not None :
155+ args .image_aspect_ratio = model .config .image_aspect_ratio
156+ else :
157+ raise ValueError ("image_aspect_ratio is not found in the model config" )
158+
149159 # Iterate over each sample in the ground truth file
150160 index = 0
151161 for sample in tqdm (gt_questions ):
152162 video_name = sample ['video_name' ]
153163 short_question = sample ['short_q' ]
154- long_question = sample ['long_q' ]
155164 index += 1
156-
165+ video_key = video_name .split ("." )[0 ]
166+ short_caption_file = os .path .join (args .output_dir , "%s.json" % video_key )
167+ if os .path .exists (short_caption_file ):
168+ print ("Finished %s." % video_name )
169+ continue
157170 # Load the video file
158- for question_type in ['short' , 'long' ]:
159- temp_path = os .path .join (args .video_dir , f"{ video_name } " )
160- print (f"Processing video: { temp_path } " )
161- if os .path .exists (temp_path ):
162- video_path = temp_path
163- question = short_question if question_type == 'short' else long_question
164- output = get_model_output (model , image_processor , tokenizer , video_path , question , args )
165- print ('question:' , question )
166- if question_type == 'short' :
167- short_caption_file .write (f"{ video_name } : { output } \n " )
168- elif question_type == 'long' :
169- long_caption_file .write (f"{ video_name } : { output } \n " )
170- else :
171- raise ValueError (f"Invalid question type: { question_type } " )
172- short_caption_file .close ()
173- long_caption_file .close ()
174- print (f"Results saved to { args .output_dir } " )
171+ temp_path = os .path .join (video_dir , f"{ video_name } " )
172+ print (f"Processing video: { temp_path } " )
173+ if os .path .exists (temp_path ):
174+ video_path = temp_path
175+ question = short_question
176+ output = get_model_output (model , image_processor , tokenizer , video_path , question , args )
177+
178+ output_dict = {video_key : output }
179+ json .dump (output_dict , open (short_caption_file , "w" ))
180+
181+ gen_pred_json (args .output_dir , args .eval_type )
182+
183+ def gen_pred_json (output_dir , eval_type ):
184+ labels_json = json .load (open (LABEL_PATHS [eval_type ]))
185+ output_files = os .listdir (output_dir )
186+ output_json = []
187+ for item in labels_json :
188+ video_name = item ["video_name" ]
189+ item_output = item
190+ item_output ['pred' ] = json .load (open (os .path .join (output_dir , "%s.json" % video_name )))[video_name ]
191+ output_json .append (item_output )
192+
193+ output_path = os .path .join (output_dir , "pred.json" )
194+ json .dump (output_json , open (output_path , "w" ))
195+ print (f"Results saved to { output_path } " )
175196
176197if __name__ == "__main__" :
177198 parser = argparse .ArgumentParser ()
178199 parser .add_argument ("--model-path" , type = str , default = "facebook/opt-350m" )
179200 parser .add_argument ("--model-base" , type = str , default = None )
180- parser .add_argument ("--model_max_length" , type = int , required = False , default = 2048 )
181- parser .add_argument ('--video_dir' , help = 'Directory containing video files.' , required = True )
201+ parser .add_argument ('--eval_type' , type = str , default = "pexels" , required = True )
182202 parser .add_argument ('--output_dir' , help = 'Directory to save the model results JSON.' , required = True )
183203 parser .add_argument ("--conv-mode" , type = str , default = "llava_v1" )
184- parser .add_argument ("--prompt_template" , type = str , help = 'The template of video caption question.' , required = True )
185204 parser .add_argument ("--temperature" , type = float , default = 0.2 )
186205 parser .add_argument ("--top_p" , type = float , default = None )
187206 parser .add_argument ("--num_beams" , type = int , default = 1 )
0 commit comments