TensorFlow Lite模型兼容性问题:Feedback Manager与oneDNN算子报错求助
解决MediaPipe手部关键点采集代码中的TensorFlow Lite相关报错
问题说明
运行基于MediaPipe的手部关键点采集Python代码时,遇到两类TensorFlow Lite相关日志提示:
- oneDNN自定义算子启用提示:提示浮点运算结果可能因计算顺序的浮点舍入误差产生细微差异
- Feedback Manager警告:提示模型需为单签名推理,已自动禁用反馈张量支持
已尝试设置TF_ENABLE_ONEDNN_OPTS=0及配置absl日志,但问题仍存在。
报错信息
2024-07-15 17:11:36.038742: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable TF_ENABLE_ONEDNN_OPTS=0. 2024-07-15 17:11:37.182406: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable TF_ENABLE_ONEDNN_OPTS=0. INFO: Created TensorFlow Lite XNNPACK delegate for CPU. WARNING: All log messages before absl::InitializeLog() is called are written to STDERR W0000 00:00:1721043702.427399 30320 inference_feedback_manager.cc:114] Feedback manager requires a model with a single signature inference. Disabling support for feedback tensors. W0000 00:00:1721043702.450288 30320 inference_feedback_manager.cc:114] Feedback manager requires a model with a single signature inference. Disabling support for feedback tensors.
运行代码
import cv2 import mediapipe as mp import csv import copy import itertools import string from pathlib import Path mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles mp_hands = mp.solutions.hands # functions def calc_landmark_list(image, landmarks): image_width, image_height = image.shape[1], image.shape[0] landmark_point = [] # Keypoint for _, landmark in enumerate(landmarks.landmark): landmark_x = min(int(landmark.x * image_width), image_width - 1) landmark_y = min(int(landmark.y * image_height), image_height - 1) # landmark_z = landmark.z landmark_point.append([landmark_x, landmark_y]) return landmark_point def pre_process_landmark(landmark_list): temp_landmark_list = copy.deepcopy(landmark_list) # Convert to relative coordinates base_x, base_y = 0, 0 for index, landmark_point in enumerate(temp_landmark_list): if index == 0: base_x, base_y = landmark_point[0], landmark_point[1] temp_landmark_list[index][0] = temp_landmark_list[index][0] - base_x temp_landmark_list[index][1] = temp_landmark_list[index][1] - base_y # Convert to a one-dimensional list temp_landmark_list = list( itertools.chain.from_iterable(temp_landmark_list)) # Normalization max_value = max(list(map(abs, temp_landmark_list))) def normalize_(n): return n / max_value temp_landmark_list = list(map(normalize_, temp_landmark_list)) return temp_landmark_list def logging_csv(letter, landmark_list): csv_path = 'keypoint.csv' with open(csv_path, 'a', newline="") as f: writer = csv.writer(f) writer.writerow([letter, *landmark_list]) alphabet = list(string.ascii_uppercase) alphabet += ['1','2','3','4','5','6','7','8','9'] # For static images: address = 'images/data/' address = Path() / 'images' / 'data/' IMAGE_FILES = [] for i in alphabet: for j in range(1199): filepath = address / str(i) / f'{j}.jpg' IMAGE_FILES.append(filepath) with mp_hands.Hands( static_image_mode=True, max_num_hands=2, min_detection_confidence=0.5) as hands: for idx, file in enumerate(IMAGE_FILES): # Read an image, flip it around y-axis for correct handedness output (see # above). image = cv2.flip(cv2.imread(file), 1) # Convert the BGR image to RGB before processing. results = hands.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) # Print handedness and draw hand landmarks on the image. # print('Handedness:', results.multi_handedness) if not results.multi_hand_landmarks: continue image_height, image_width, _ = image.shape annotated_image = image.copy() for hand_landmarks, handedness in zip(results.multi_hand_landmarks,results.multi_handedness): landmark_list = calc_landmark_list(annotated_image, hand_landmarks) # Conversion to relative coordinates / normalized coordinates pre_processed_landmark_list = pre_process_landmark(landmark_list) logging_csv(file[12],pre_processed_landmark_list)
已尝试的解决代码
import absl.logging absl.logging.set_verbosity(absl.logging.INFO) absl.logging.use_absl_handler() import os os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
解决方案
1. 解决oneDNN自定义算子提示
问题出在环境变量设置时机太晚——MediaPipe和TensorFlow在导入时就已经加载了相关模块,后续设置的环境变量不会生效。
修正方法:将环境变量设置放在所有导入语句的最开头:
import os # 先关闭oneDNN算子 os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' # 再导入其他模块 import cv2 import mediapipe as mp # ... 其余代码保持不变
2. 解决Feedback Manager警告与absl日志提示
Feedback Manager警告是MediaPipe内部TF Lite模型的兼容性问题,不影响功能;absl日志提示是初始化顺序导致的。可以通过调整日志级别屏蔽这些无关输出:
完整前置配置代码:
import os # 关闭oneDNN算子 os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' # 屏蔽TensorFlow的Info和Warning级日志 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 配置absl日志只输出错误信息 import absl.logging absl.logging.set_verbosity(absl.logging.ERROR) absl.logging.use_absl_handler() # 之后再导入业务模块 import cv2 import mediapipe as mp # ... 其余代码保持不变
补充说明
这些日志提示本身不会影响代码的功能运行,只是会干扰控制台输出。如果不需要完全屏蔽,也可以保留日志,但调整级别后会让控制台输出更简洁。
内容的提问来源于stack exchange,提问作者Ratnesh
相关产品推荐
相关产品推荐

