如何修复TensorFlow目标检测报OSError: invalid face handle错误
问题背景
实操TensorFlow实时目标检测教程到最终摄像头推理环节时,程序抛出OSError: invalid face handle错误,沿调用链路排查后,初步怀疑ImageFont.py文件内size, offset = self.font.getsize(text, "L", direction, features, language)行是报错触发点。
复现代码
import cv2 import numpy as np import os from object_detection.utils import label_map_util from object_detection.utils import visualization_utils as viz_utils from object_detection.utils import config_util from object_detection.builders import model_builder import tensorflow as tf from object_detection.utils import config_util from object_detection.protos import pipeline_pb2 from google.protobuf import text_format WORKSPACE_PATH = 'Tensorflow/workspace' SCRIPTS_PATH = 'Tensorflow/scripts' APIMODEL_PATH = 'Tensorflow/models' ANNOTATION_PATH = WORKSPACE_PATH+'/annotations' IMAGE_PATH = WORKSPACE_PATH+'/images' MODEL_PATH = WORKSPACE_PATH+'/models' PRETRAINED_MODEL_PATH = WORKSPACE_PATH+'/pre-trained-models' CONFIG_PATH = MODEL_PATH+'/my_ssd_mobnet/pipeline.config' CHECKPOINT_PATH = MODEL_PATH+'/my_ssd_mobnet/' CUSTOM_MODEL_NAME = 'my_ssd_mobnet' CONFIG_PATH = MODEL_PATH+'/'+CUSTOM_MODEL_NAME+'/pipeline.config' # 加载管线配置、构建检测模型 configs = config_util.get_configs_from_pipeline_file(CONFIG_PATH) detection_model = model_builder.build(model_config=configs['model'], is_training=False) # 恢复检查点 ckpt = tf.compat.v2.train.Checkpoint(model=detection_model) ckpt.restore(os.path.join(CHECKPOINT_PATH, 'ckpt-11')).expect_partial() @tf.function def detect_fn(image): image, shapes = detection_model.preprocess(image) prediction_dict = detection_model.predict(image, shapes) detections = detection_model.postprocess(prediction_dict, shapes) return detections cap = cv2.VideoCapture(0) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) category_index = label_map_util.create_category_index_from_labelmap(ANNOTATION_PATH+'/label_map.pbtxt') while True: ret, frame = cap.read() image_np = np.array(frame) input_tensor = tf.convert_to_tensor(np.expand_dims(image_np, 0), dtype=tf.float32) detections = detect_fn(input_tensor) num_detections = int(detections.pop('num_detections')) detections = {key: value[0, :num_detections].numpy() for key, value in detections.items()} detections['num_detections'] = num_detections # 检测类别需转为整型 detections['detection_classes'] = detections['detection_classes'].astype(np.int64) label_id_offset = 1 image_np_with_detections = image_np.copy() viz_utils.visualize_boxes_and_labels_on_image_array( image_np_with_detections, detections['detection_boxes'], detections['detection_classes']+label_id_offset, detections['detection_scores'], category_index, use_normalized_coordinates=True, max_boxes_to_draw=5, min_score_thresh=.5, agnostic_mode=False) cv2.imshow('object detection', cv2.resize(image_np_with_detections, (800, 600))) if cv2.waitKey(1) & 0xFF == ord('q'): cap.release() break
报错堆栈
Traceback (most recent call last): File "c:/Users/Rohan/Desktop/facial recognition/RealTimeObjectDetection-main/RealTimeObjectDetection-main/test.py", line 73, in <module> agnostic_mode=False) File "C:\Users\Rohan\AppData\Local\Programs\Python\Python37\lib\site-packages\object_detection\utils\visualization_utils.py", line 1259, in visualize_boxes_and_labels_on_image_array use_normalized_coordinates=use_normalized_coordinates) File "C:\Users\Rohan\AppData\Local\Programs\Python\Python37\lib\site-packages\object_detection\utils\visualization_utils.py", line 162, in draw_bounding_box_on_image_array use_normalized_coordinates) File "C:\Users\Rohan\AppData\Local\Programs\Python\Python37\lib\site-packages\object_detection\utils\visualization_utils.py", line 219, in draw_bounding_box_on_image display_str_heights = [font.getsize(ds)[1] for ds in display_str_list] File "C:\Users\Rohan\AppData\Local\Programs\Python\Python37\lib\site-packages\object_detection\utils\visualization_utils.py", line 219, in <listcomp> display_str_heights = [font.getsize(ds)[1] for ds in display_str_list] File "C:\Users\Rohan\AppData\Local\Programs\Python\Python37\lib\site-packages\PIL\ImageFont.py", line 414, in getsize size, offset = self.font.getsize(text, "L", direction, features, language) OSError: invalid face handle
故障原因
该错误由Pillow库版本和TensorFlow目标检测API的可视化模块字体加载逻辑不兼容导致:高版本Pillow加载默认字体失败时会返回无效的字体句柄,后续调用getsize()方法计算文本尺寸时就会触发invalid face handle报错。
解决方案
- 方案一:降级Pillow到兼容版本,执行命令
pip install pillow==8.4.0,安装完成后重新运行脚本即可正常显示检测框和标签。 - 方案二:手动修改可视化工具的字体加载逻辑,找到本地
visualization_utils.py文件中draw_bounding_box_on_image函数内加载字体的代码段,显式指定系统内存在的有效ttf字体路径,比如Windows系统可替换为加载C:/Windows/Fonts/arial.ttf,避免加载无效默认字体。
内容的提问来源于stack exchange,提问作者Rohan
相关产品推荐
相关产品推荐

