1818import glob
1919import os
2020
21+ #Select a model to use, in this case VGG16
2122model = VGG16 (weights = 'imagenet' , include_top = True , input_tensor = None , input_shape = None , pooling = None , classes = 1000 )
2223#Check with 'print(model.summary())', in this case it is "block5_conv3"
2324last_conv_layer_name = "block5_conv3"
24- #Include layers between last convolutional layer and prediction layer
25+ #Must include layers between last convolutional layer and prediction layer
26+ #Layer names can be found through 'print(model.summary())'
2527classifier_layer_names = ["block5_pool" , "flatten" , "fc1" , "fc2" , "predictions" ]
2628
29+ #This function is called from 'make_gradcam_heatmap'
30+ #Takes iaage_path from 'get_command_line_arguments', turns into it an array
2731def get_img_array (img_path , size ):
2832 img = tensorflow .keras .preprocessing .image .load_img (img_path , target_size = (224 , 224 ))
2933 # `array` is a float32 Numpy array
@@ -33,12 +37,17 @@ def get_img_array(img_path, size):
3337 array = np .expand_dims (array , axis = 0 )
3438 return array
3539
36- #This replaces several functions from visualization.py
40+ #'make_gradcam_heatmap' is main function and ultimately returns heatmap superimposed onto the input image(s)
41+
42+ #inputs are the image path specified in the command line, the last convolutional layer and
43+ #the classifier layer names of which both are defined above and depend on your model, and the output path
44+ #for our heatmap superimposed onto original image which are specified in the script's final if statement
3745def make_gradcam_heatmap (
3846 img_path , model , last_conv_layer_name , classifier_layer_names , output_path
3947):
40-
48+ #pre_processes the array returned from 'get_img_array'
4149 img_array = preprocess_input (get_img_array (img_path , size = (224 , 224 )))
50+
4251 # First, we create a model that maps the input image to the activations
4352 # of the last conv layer
4453 last_conv_layer = model .get_layer (last_conv_layer_name )
@@ -55,9 +64,11 @@ def make_gradcam_heatmap(
5564 # Then, we compute the gradient of the top predicted class for our input image
5665 # with respect to the activations of the last conv layer
5766 with tensorflow .GradientTape () as tape :
67+
5868 # Compute activations of the last conv layer and make the tape watch it
5969 last_conv_layer_output = last_conv_layer_model (img_array )
6070 tape .watch (last_conv_layer_output )
71+
6172 # Compute class predictions
6273 preds = classifier_model (last_conv_layer_output )
6374 top_pred_index = tensorflow .argmax (preds [0 ])
@@ -111,20 +122,27 @@ def make_gradcam_heatmap(
111122 #Save the the superimposed image to the output path
112123 superimposed_img .save (output_path )
113124
114-
125+ #Runs body of code for entirety of videoframs_path (folder specified in command line)
115126def process_video (videoframes_path , output_prefix ):
116127 counter = 0
128+ #define output directory
117129 output_dir = output_prefix + "_output"
130+
131+ #Creates directory output directoy if it doesn't already exist
118132 if not os .path .exists (output_dir ):
119133 os .makedirs (output_dir )
120134 for input_path in sorted (glob .glob (videoframes_path + "/*.jpg" )):
121- counter += 1
135+ counter +=
136+
122137 output_path = output_dir + "/result-" + str (counter ).zfill (4 ) + '.jpg'
123138
139+ #Runs main function with specified image_path, output_prefix, and layers defined near top of script
124140 make_gradcam_heatmap (input_path , model , last_conv_layer_name , classifier_layer_names , output_path )
125141
142+ #Function for taking inputs through the command line
126143def get_command_line_arguments ():
127144 parser = ArgumentParser ()
145+ #We specify either image or video to
128146 parser .add_argument ("--process" , choices = ["image" , "video" ], required = True ,
129147 dest = "process_type" , help = "Process a single image or video" )
130148 parser .add_argument ("--path" , required = True , dest = "path" ,
@@ -134,17 +152,25 @@ def get_command_line_arguments():
134152
135153args = get_command_line_arguments ()
136154
155+ #If process is specified as 'image', defines image_path and output_prefix according to command line argument
137156if args .process_type == "image" :
157+ #image path is location of image that we want to generate a heatmap for
138158 image_path = args .path
139159 output_prefix = os .path .splitext (os .path .basename (image_path ))[0 ]
160+ #Runs main function with specified image_path and output_prefix from command line
161+ #layers defined near top of script
140162 make_gradcam_heatmap (image_path , model , last_conv_layer_name , classifier_layer_names , output_prefix + "_output.jpg" )
141163
142164 #Plot the superimposed image
143165 img = mpimg .imread (output_prefix + "_output.jpg" )
144166 plt .imshow (img )
145167 plt .show ()
146168
169+ #If process is specified as 'image', defines videoframes_path and output_prefix according to command line argument
147170elif args .process_type == "video" :
171+ #videoframes_path is directory with the video frames split by ffmpeg
148172 videoframes_path = args .path
173+ #will be used to specify or create output folder
149174 output_prefix = os .path .dirname (videoframes_path )
175+ #Runs 'process_video' function with inputs taken from command line
150176 heatmaps = process_video (videoframes_path , output_prefix )
0 commit comments