def _detect(setting: Dict[Any, Any], image) -> List[Dict[Any, Any]]: start = datetime.datetime.now() # Generate output tensor targets for filtered bounding boxes. # TODO: Wrap these backend operations with Keras layers. yolo_outputs = yolo_head(setting['yolo_model'].output, setting['anchors'], len(setting['class_names'])) input_image_shape = kback.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval(yolo_outputs, input_image_shape, score_threshold=args.score_threshold, iou_threshold=args.iou_threshold) print('spent time(yolo_eval)', datetime.datetime.now() - start) if setting[ 'is_fixed_size']: # TODO: When resizing we can use minibatch input. resized_image = image.resize( tuple(reversed(setting['model_image_size'])), Image.BICUBIC) image_data = np.array(resized_image, dtype='float32') else: # Due to skip connection + max pooling in YOLO_v2, inputs must have # width and height as multiples of 32. new_image_size = (image.width - (image.width % 32), image.height - (image.height % 32)) resized_image = image.resize(new_image_size, Image.BICUBIC) image_data = np.array(resized_image, dtype='float32') print(image_data.shape) image_data /= 255. image_data = np.expand_dims(image_data, 0) # Add batch dimension. print('spent time(before run)', datetime.datetime.now() - start) out_boxes, out_scores, out_classes = setting['sess'].run( [boxes, scores, classes], feed_dict={ setting['yolo_model'].input: image_data, input_image_shape: [image.size[1], image.size[0]], kback.learning_phase(): 0 }) print('spent time(after run)', datetime.datetime.now() - start) detected_items = [] for i, c in reversed(list(enumerate(out_classes))): predicted_class = setting['class_names'][c] box = out_boxes[i] score = out_scores[i] detected_items.append({ 'class': predicted_class, 'box': box.tolist(), 'score': score.tolist(), }) print('detected_items', detected_items) print('spent time(_detect)', datetime.datetime.now() - start) return detected_items
def YOLO_predict(img, batch_img, sess, model, anchors, n_classes): yolo_outputs = yolo_head(model.output, anchors, n_classes) input_image_shape = K.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval(yolo_outputs, input_image_shape) out_boxes, out_scores, out_classes = sess.run( [boxes, scores, classes], feed_dict={ model.input: batch_img, input_image_shape: [img.shape[0], img.shape[1]], K.learning_phase(): 0 }) return out_boxes, out_scores, out_classes
def draw(model_body, class_names, anchors, image_data, image_set='val', weights_name='trained_stage_3_best.h5', out_path="output_images", save_all=True): if image_set == 'train': image_data = np.array([np.expand_dims(image, axis=0) for image in image_data[:int(len(image_data)*.9)]]) elif image_set == 'val': image_data = np.array([np.expand_dims(image, axis=0) for image in image_data[int(len(image_data)*.9):]]) elif image_set == 'all': image_data = np.array([np.expand_dims(image, axis=0) for image in image_data]) else: ValueError("draw argument image_set must be 'train', 'val', or 'all'") # model.load_weights(weights_name) print(image_data.shape) model_body.load_weights(weights_name) # Create output variables for prediction. yolo_outputs = yolo_head(model_body.output, anchors, len(class_names)) input_image_shape = K.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval( yolo_outputs, input_image_shape, score_threshold=0.07, iou_threshold=0.0) # Run prediction on overfit image. sess = K.get_session() # TODO: Remove dependence on Tensorflow session. if not os.path.exists(out_path): os.makedirs(out_path) for i in range(len(image_data)): out_boxes, out_scores, out_classes = sess.run( [boxes, scores, classes], feed_dict={ model_body.input: image_data[i], input_image_shape: [image_data.shape[2], image_data.shape[3]], K.learning_phase(): 0 }) print('Found {} boxes for image.'.format(len(out_boxes))) print("Boxes:",out_boxes) # Plot image with predicted boxes. image_with_boxes = draw_boxes_(image_data[i][0], out_boxes, out_classes, class_names, out_scores) print("--------------------------------------------") # Save the image: if save_all or (len(out_boxes) > 0): image = PIL.Image.fromarray(image_with_boxes) image.save(os.path.join(out_path,str(i)+'.png'))
import scipy.misc from keras import backend as K from keras.models import load_model from YAD2K.yad2k.models.keras_yolo import yolo_head, yolo_eval from network.yolo_utils import read_classes, read_anchors, preprocess_image, generate_colors, draw_boxes sess = K.get_session() class_names = read_classes("YAD2K/model_data/coco_classes.txt") anchors = read_anchors("YAD2K/model_data/yolo_anchors.txt") # image_shape = (720., 1280.) image_shape = (600., 800.) yolo_model = load_model("YAD2K/model_data/yolo.h5") yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names)) scores, boxes, classes = yolo_eval(yolo_outputs, image_shape, score_threshold=0.4) def predict(): global sess imgs = os.listdir('imgs')[:1] for img in imgs: out_scores, out_boxes, out_classes = yolo_predict(sess, img) print('out_scores', out_scores) print('out_boxes', out_boxes) print('out_classes', out_classes) def yolo_predict(sess, image_file):
for x in range(len(class_names))] colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors)) random.seed(10101) # Fixed seed for consistent colors across runs. random.shuffle(colors) # Shuffle colors to decorrelate adjacent classes. random.seed(None) # Reset seed to default. # Generate output tensor targets for filtered bounding boxes. # TODO: Wrap these backend operations with Keras layers. yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names)) input_image_shape = K.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval( yolo_outputs, input_image_shape, score_threshold=args.score_threshold, iou_threshold=args.iou_threshold) # Save the output into a compact JSON file. outfile = open('output/game_data.json', 'w') # This will be appended with an object for every frame. data_to_write = [] def test_yolo(image, image_file_name): if is_fixed_size: # TODO: When resizing we can use minibatch input. resized_image = image.resize(tuple(reversed(model_image_size)), Image.BICUBIC) image_data = np.array(resized_image, dtype='float32') else: # Due to skip connection + max pooling in YOLO_v2, inputs must have
def _main(args, frames_paths, crops_bboxes, crop_value, resize_frames=None, verbose=1, person_only=True, allowed_number_of_boxes=100): ''' :param args: yolo model args like in YAD2K :param frames_paths: list of paths to frame images :param crops_bboxes: list of lists - crops per frames :param verbose: :param person_only: :return: ''' print("frames_paths", len(frames_paths), frames_paths) print("crops_bboxes", len(crops_bboxes), crops_bboxes) model_path = os.path.expanduser(args["model_path"]) print(model_path) assert model_path.endswith('.h5'), 'Keras model must be a .h5 file.' anchors_path = os.path.expanduser(args["anchors_path"]) classes_path = os.path.expanduser(args["classes_path"]) sess = K.get_session() # TODO: Remove dependence on Tensorflow session. with open(classes_path) as f: class_names = f.readlines() class_names = [c.strip() for c in class_names] with open(anchors_path) as f: anchors = f.readline() anchors = [float(x) for x in anchors.split(',')] anchors = np.array(anchors).reshape(-1, 2) yolo_model = load_model(model_path) # Verify model, anchors, and classes are compatible num_classes = len(class_names) num_anchors = len(anchors) # TODO: Assumes dim ordering is channel last # model_output_channels = yolo_model.layers[-1].output_shape[-1] # assert model_output_channels == num_anchors * (num_classes + 5), \ # 'Mismatch between model and given anchor and class sizes. ' \ # 'Specify matching anchors and classes with --anchors_path and ' \ # '--classes_path flags.' if verbose > 0: print('{} model, anchors, and classes loaded.'.format(model_path)) # Check if model is fully convolutional, assuming channel last order. model_image_size = yolo_model.layers[0].input_shape[1:3] is_fixed_size = model_image_size != (None, None) # Generate colors for drawing bounding boxes. hsv_tuples = [(x / len(class_names), 1., 1.) for x in range(len(class_names))] colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors)) random.seed(10101) # Fixed seed for consistent colors across runs. random.shuffle(colors) # Shuffle colors to decorrelate adjacent classes. random.seed(None) # Reset seed to default. # Generate output tensor targets for filtered bounding boxes. # TODO: Wrap these backend operations with Keras layers. ### old # yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names))###差异 # input_image_shape = K.placeholder(shape=(2, )) ### if ("v2" in model_path): from YAD2K.yad2k.models.keras_yolo import yolo_eval, yolo_head ###两个yoloV2 yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names)) elif ("v3" in model_path): from kyolov3.ky.yolo3.model import yolo_head, yolo_eval yolo_outputs = yolo_model.output else: from kyolov3.ky.yolo3.model import yolo_head, yolo_eval yolo_outputs = yolo_model.output ### 看看会不会错 yolo_model.output == feat == yolo_outputs[l] input_image_shape = K.placeholder(shape=(2, )) ####### EVALUATION boxes, scores, classes = yolo_eval(yolo_outputs, anchors, num_classes, input_image_shape, score_threshold=args["score_threshold"], iou_threshold=args["iou_threshold"], max_boxes=allowed_number_of_boxes) pureEval_times = [] ioPlusEval_times = [] bboxes = [] images_processed = 0 evaluation_time = 0 ### PROCESS FILES for frame_i in range(0, len(frames_paths)): start_loop = timer() images_processed += 1 frame_path = frames_paths[frame_i] frame = Image.open(frame_path) if resize_frames is not None: resize_to = resize_frames[frame_i] ow, oh = frame.size nw = ow * resize_to nh = oh * resize_to frame = frame.resize((int(nw), int(nh)), Image.ANTIALIAS) crops_in_frame = crops_bboxes[frame_i] #print("Frame", frame_i, " with ", len(crops_in_frame), " crops.") sys.stdout.write("\rFrame " + str(frame_i) + " with " + str(len(crops_in_frame)) + " crops.") sys.stdout.flush() for crop_i in range(0, len(crops_in_frame)): crop = crops_in_frame[crop_i] area = crop[1] #area = (int(w_crop[0]), int(h_crop[0]), int(w_crop[0] + scale * crop), int(h_crop[0] + scale * crop)) cropped_img = frame.crop(box=area) cropped_img = cropped_img.resize( (int(crop_value), int(crop_value)), resample=Image.ANTIALIAS) cropped_img.load() """ print("////////////////////////////////////////////////") print("area",area) print("crop_value",crop_value) print("cropped_img", cropped_img.size) cropped_img.show() print("////////////////////////////////////////////////") """ image = cropped_img """ image_data = np.array(image, dtype='float32') """ if is_fixed_size: # TODO: When resizing we can use minibatch input. resized_image = image.resize(tuple(reversed(model_image_size)), Image.BICUBIC) image_data = np.array(resized_image, dtype='float32') else: # Due to skip connection + max pooling in YOLO_v2, inputs must have # width and height as multiples of 32. new_image_size = (image.width - (image.width % 32), image.height - (image.height % 32)) resized_image = image.resize(new_image_size, Image.BICUBIC) image_data = np.array(resized_image, dtype='float32') print(image_data.shape) image_data /= 255. image_data = np.expand_dims(image_data, 0) # Add batch dimension. if images_processed < 2: print("# image size: ", image_data.shape, image.size) ################# START ################# start_eval = timer() out_boxes, out_scores, out_classes = sess.run( [boxes, scores, classes], feed_dict={ yolo_model.input: image_data, input_image_shape: [image.size[1], image.size[0]], K.learning_phase(): 0 }) end_eval = timer() ################# END ################# evaluation_time = (end_eval - start_eval) pureEval_times.append(evaluation_time) people = 0 bboxes_image = [] #print(num_frames, num_crops) for i, c in reversed(list(enumerate(out_classes))): predicted_class = class_names[c] if predicted_class == 'person': people += 1 if person_only and (predicted_class != 'person'): continue box = out_boxes[i] score = out_scores[i] #print(predicted_class, box, score) bboxes_image.append([predicted_class, box, score, c]) if verbose > 0: num = len(out_boxes) if person_only: num = people print('Found {} boxes in crop {} of frame {} in {}s'.format( num, crop_i, frame_i, evaluation_time)) bboxes.append(bboxes_image) end_loop = timer() loop_time = (end_loop - start_loop) ioPlusEval_times.append(loop_time - evaluation_time) #sess.close() return bboxes
def run_nn(hWnd): global loaded model_path = os.path.expanduser('YAD2K/model_data/yolo.h5') anchors_path = os.path.expanduser('YAD2K/model_data/yolo_anchors.txt') classes_path = os.path.expanduser('YAD2K/model_data/league_classes.txt') sess = K.get_session() # TODO: Remove dependence on Tensorflow session. with open(classes_path) as f: class_names = f.readlines() class_names = [c.strip() for c in class_names] with open(anchors_path) as f: anchors = f.readline() anchors = [float(x) for x in anchors.split(',')] anchors = np.array(anchors).reshape(-1, 2) yolo_model, _ = create_model(anchors, class_names) yolo_model.load_weights('trained_stage_3_best.h5') # Verify model, anchors, and classes are compatible num_classes = len(class_names) num_anchors = len(anchors) # TODO: Assumes dim ordering is channel last model_output_channels = yolo_model.layers[-1].output_shape[-1] assert model_output_channels == num_anchors * ( num_classes + 5), 'Mismatch between model and given anchor and class sizes. ' print('{} model, anchors, and classes loaded.'.format(model_path)) # Check if model is fully convolutional, assuming channel last order. model_image_size = yolo_model.layers[0].input_shape[1:3] is_fixed_size = model_image_size != (None, None) # Generate colors for drawing bounding boxes. hsv_tuples = [(x / len(class_names), 1., 1.) for x in range(len(class_names))] colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors)) random.seed(10101) # Fixed seed for consistent colors across runs. random.shuffle(colors) # Shuffle colors to decorrelate adjacent classes. random.seed(None) # Reset seed to default. # Generate output tensor targets for filtered bounding boxes. # TODO: Wrap these backend operations with Keras layers. yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names)) input_image_shape = K.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval(yolo_outputs, input_image_shape, score_threshold=args.score_threshold, iou_threshold=args.iou_threshold) # Save the output into a compact JSON file. outfile = open('output/game_data.json', 'w') # This will be appended with an object for every frame. data_to_write = [] loaded = True win32gui.RedrawWindow(hWnd, None, None, win32con.RDW_INVALIDATE | win32con.RDW_ERASE) with mss.mss() as sct: monitor = {'top': 0, 'left': 0, 'width': 1920, 'height': 1080} while 'Screen capturing': last_time = time.time() # Get raw pixels from the screen, save it to a Numpy array img = np.array(sct.grab(monitor)) img = Image.fromarray(img) img.load() background = Image.new("RGB", img.size, (255, 255, 255)) background.paste(img, mask=img.split()[3]) test_yolo(background, is_fixed_size, model_image_size, sess, boxes, scores, classes, yolo_model, input_image_shape, class_names, colors) win32gui.RedrawWindow(hWnd, None, None, win32con.RDW_INVALIDATE | win32con.RDW_ERASE) # img = test_yolo(background) # basewidth = 700 # wpercent = (basewidth/float(img.size[0])) # hsize = int((float(img.size[1])*float(wpercent))) # img = img.resize((basewidth,hsize), Image.ANTIALIAS) # img = np.array(img) # # Display the picture # cv2.imshow('OpenCV/Numpy normal', img) # Press "q" to quit if cv2.waitKey(25) & 0xFF == ord(';'): cv2.destroyAllWindows() break sess.close() return
def _main(args): voc_path = os.path.expanduser(args.data_path) classes_path = os.path.expanduser(args.classes_path) anchors_path = os.path.expanduser(args.anchors_path) with open(classes_path) as f: class_names = f.readlines() class_names = [c.strip() for c in class_names] if os.path.isfile(anchors_path): with open(anchors_path) as f: anchors = f.readline() anchors = [float(x) for x in anchors.split(',')] anchors = np.array(anchors).reshape(-1, 2) else: anchors = YOLO_ANCHORS voc = h5py.File(voc_path, 'r') image = PIL.Image.open(io.BytesIO(voc['train/images'][28])) orig_size = np.array([image.width, image.height]) orig_size = np.expand_dims(orig_size, axis=0) # Image preprocessing. image = image.resize((416, 416), PIL.Image.BICUBIC) image_data = np.array(image, dtype=np.float) image_data /= 255. # Box preprocessing. # Original boxes stored as 1D list of class, x_min, y_min, x_max, y_max. boxes = voc['train/boxes'][28] boxes = boxes.reshape((-1, 5)) # Get extents as y_min, x_min, y_max, x_max, class for comparision with # model output. boxes_extents = boxes[:, [2, 1, 4, 3, 0]] # Get box parameters as x_center, y_center, box_width, box_height, class. boxes_xy = 0.5 * (boxes[:, 3:5] + boxes[:, 1:3]) boxes_wh = boxes[:, 3:5] - boxes[:, 1:3] boxes_xy = boxes_xy / orig_size boxes_wh = boxes_wh / orig_size boxes = np.concatenate((boxes_xy, boxes_wh, boxes[:, 0:1]), axis=1) # Precompute detectors_mask and matching_true_boxes for training. # Detectors mask is 1 for each spatial position in the final conv layer and # anchor that should be active for the given boxes and 0 otherwise. # Matching true boxes gives the regression targets for the ground truth box # that caused a detector to be active or 0 otherwise. detectors_mask_shape = (13, 13, 5, 1) matching_boxes_shape = (13, 13, 5, 5) detectors_mask, matching_true_boxes = preprocess_true_boxes( boxes, anchors, [416, 416]) # Create model input layers. image_input = Input(shape=(416, 416, 3)) boxes_input = Input(shape=(None, 5)) detectors_mask_input = Input(shape=detectors_mask_shape) matching_boxes_input = Input(shape=matching_boxes_shape) print('Boxes:') print(boxes) print('Box corners:') print(boxes_extents) print('Active detectors:') print(np.where(detectors_mask == 1)[:-1]) print('Matching boxes for active detectors:') print(matching_true_boxes[np.where(detectors_mask == 1)[:-1]]) # Create model body. model_body = yolo_body(image_input, len(anchors), len(class_names)) model_body = Model(image_input, model_body.output) # Place model loss on CPU to reduce GPU memory usage. with tf.device('/cpu:0'): # TODO: Replace Lambda with custom Keras layer for loss. model_loss = Lambda(yolo_loss, output_shape=(1, ), name='yolo_loss', arguments={ 'anchors': anchors, 'num_classes': len(class_names) })([ model_body.output, boxes_input, detectors_mask_input, matching_boxes_input ]) model = Model( [image_input, boxes_input, detectors_mask_input, matching_boxes_input], model_loss) model.compile( optimizer='adam', loss={ 'yolo_loss': lambda y_true, y_pred: y_pred }) # This is a hack to use the custom loss function in the last layer. # Add batch dimension for training. image_data = np.expand_dims(image_data, axis=0) boxes = np.expand_dims(boxes, axis=0) detectors_mask = np.expand_dims(detectors_mask, axis=0) matching_true_boxes = np.expand_dims(matching_true_boxes, axis=0) num_steps = 1000 # TODO: For full training, put preprocessing inside training loop. # for i in range(num_steps): # loss = model.train_on_batch( # [image_data, boxes, detectors_mask, matching_true_boxes], # np.zeros(len(image_data))) model.fit([image_data, boxes, detectors_mask, matching_true_boxes], np.zeros(len(image_data)), batch_size=1, epochs=num_steps) model.save_weights('overfit_weights.h5') # Create output variables for prediction. yolo_outputs = yolo_head(model_body.output, anchors, len(class_names)) input_image_shape = K.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval(yolo_outputs, input_image_shape, score_threshold=.3, iou_threshold=.9) # Run prediction on overfit image. sess = K.get_session() # TODO: Remove dependence on Tensorflow session. out_boxes, out_scores, out_classes = sess.run( [boxes, scores, classes], feed_dict={ model_body.input: image_data, input_image_shape: [image.size[1], image.size[0]], K.learning_phase(): 0 }) print('Found {} boxes for image.'.format(len(out_boxes))) print(out_boxes) # Plot image with predicted boxes. image_with_boxes = draw_boxes(image_data[0], out_boxes, out_classes, class_names, out_scores) plt.imshow(image_with_boxes, interpolation='nearest') plt.show()
def _main(args): model_path = os.path.expanduser(args.model_path) assert model_path.endswith('.h5'), 'Keras model must be a .h5 file.' anchors_path = os.path.expanduser(args.anchors_path) classes_path = os.path.expanduser(args.classes_path) test_path = os.path.expanduser(args.test_path) output_path = os.path.expanduser(args.output_path) if not os.path.exists(output_path): print('Creating output path {}'.format(output_path)) os.mkdir(output_path) sess = K.get_session() # TODO: Remove dependence on Tensorflow session. with open(classes_path) as f: class_names = f.readlines() class_names = [c.strip() for c in class_names] with open(anchors_path) as f: anchors = f.readline() anchors = [float(x) for x in anchors.split(',')] anchors = np.array(anchors).reshape(-1, 2) yolo_model = load_model(model_path) # Verify model, anchors, and classes are compatible num_classes = len(class_names) num_anchors = len(anchors) # TODO: Assumes dim ordering is channel last model_output_channels = yolo_model.layers[-1].output_shape[-1] assert model_output_channels == num_anchors * (num_classes + 5), \ 'Mismatch between model and given anchor and class sizes. ' \ 'Specify matching anchors and classes with --anchors_path and ' \ '--classes_path flags.' print('{} model, anchors, and classes loaded.'.format(model_path)) # Check if model is fully convolutional, assuming channel last order. model_image_size = yolo_model.layers[0].input_shape[1:3] is_fixed_size = model_image_size != (None, None) # Generate colors for drawing bounding boxes. hsv_tuples = [(x / len(class_names), 1., 1.) for x in range(len(class_names))] colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) colors = list( map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors)) random.seed(10101) # Fixed seed for consistent colors across runs. random.shuffle(colors) # Shuffle colors to decorrelate adjacent classes. random.seed(None) # Reset seed to default. # Generate output tensor targets for filtered bounding boxes. # TODO: Wrap these backend operations with Keras layers. yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names)) input_image_shape = K.placeholder(shape=(2, )) boxes, scores, classes = yolo_eval(yolo_outputs, input_image_shape, score_threshold=args.score_threshold, iou_threshold=args.iou_threshold) for image_file in os.listdir(test_path): try: image_type = imghdr.what(os.path.join(test_path, image_file)) if not image_type: continue except IsADirectoryError: continue image = Image.open(os.path.join(test_path, image_file)) if is_fixed_size: # TODO: When resizing we can use minibatch input. resized_image = image.resize(tuple(reversed(model_image_size)), Image.BICUBIC) image_data = np.array(resized_image, dtype='float32') else: # Due to skip connection + max pooling in YOLO_v2, inputs must have # width and height as multiples of 32. new_image_size = (image.width - (image.width % 32), image.height - (image.height % 32)) resized_image = image.resize(new_image_size, Image.BICUBIC) image_data = np.array(resized_image, dtype='float32') print(image_data.shape) image_data /= 255. image_data = np.expand_dims(image_data, 0) # Add batch dimension. out_boxes, out_scores, out_classes = sess.run( [boxes, scores, classes], feed_dict={ yolo_model.input: image_data, input_image_shape: [image.size[1], image.size[0]], K.learning_phase(): 0 }) print('Found {} boxes for {}'.format(len(out_boxes), image_file)) font = ImageFont.truetype( font= 'E:\\virtualdestop\AttentionPipeline-master\\video_parser_v1\YAD2K\\font\FiraMono-Medium.otf', size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32')) thickness = (image.size[0] + image.size[1]) // 300 for i, c in reversed(list(enumerate(out_classes))): predicted_class = class_names[c] box = out_boxes[i] score = out_scores[i] label = '{} {:.2f}'.format(predicted_class, score) draw = ImageDraw.Draw(image) label_size = draw.textsize(label, font) top, left, bottom, right = box top = max(0, np.floor(top + 0.5).astype('int32')) left = max(0, np.floor(left + 0.5).astype('int32')) bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32')) right = min(image.size[0], np.floor(right + 0.5).astype('int32')) print(label, (left, top), (right, bottom)) if top - label_size[1] >= 0: text_origin = np.array([left, top - label_size[1]]) else: text_origin = np.array([left, top + 1]) # My kingdom for a good redistributable image drawing library. for i in range(thickness): draw.rectangle([left + i, top + i, right - i, bottom - i], outline=colors[c]) draw.rectangle( [tuple(text_origin), tuple(text_origin + label_size)], fill=colors[c]) draw.text(text_origin, label, fill=(0, 0, 0), font=font) del draw image.save(os.path.join(output_path, image_file), quality=90) sess.close()