diff --git a/classifier/food_classifier_app.py b/classifier/food_classifier_app.py index b1b9442..4d74891 100644 --- a/classifier/food_classifier_app.py +++ b/classifier/food_classifier_app.py @@ -125,6 +125,27 @@ class FoodClassifierApp: print(f"模型加载失败: {e}") self.model = None + def extract_true_class_from_path(self, file_path): + """从文件路径中提取真实类别(上一级目录名)""" + try: + # 标准化路径 + normalized_path = os.path.normpath(file_path) + # 获取目录路径 + dir_path = os.path.dirname(normalized_path) + # 获取上一级目录名(即类别名) + true_class = os.path.basename(dir_path) + + # 检查是否是已知的食物类别 + if true_class in self.food_classes: + return true_class + else: + # 如果不是已知类别,返回None表示未知 + return None + + except Exception as e: + print(f"提取真实类别失败: {e}") + return None + def load_image_with_chinese_path(self, file_path): """使用支持中文路径的方法加载图片""" try: @@ -337,11 +358,15 @@ class FoodClassifierApp: messagebox.showerror("错误", f"无法读取图片: {file_path}") return + # 从文件路径中提取真实类别(上一级目录名) + true_class = self.extract_true_class_from_path(file_path) + # 添加到列表 image_info = { 'path': file_path, 'name': os.path.basename(file_path), 'image': image, + 'true_class': true_class, 'recognized': False, 'result': None } @@ -390,15 +415,42 @@ class FoodClassifierApp: ) name_label.pack(fill="x", padx=5, pady=2) - # 状态 - status = "已识别" if img_info['recognized'] else "未识别" + # 状态和真实类别 + if img_info['recognized'] and img_info.get('result'): + result = img_info['result'] + is_correct = result.get('is_correct') + if is_correct is True: + status = "已识别 ✓" + status_color = "green" + elif is_correct is False: + status = "已识别 ✗" + status_color = "red" + else: + status = "已识别 ?" + status_color = "orange" + else: + status = "未识别" + status_color = None + status_label = ctk.CTkLabel( info_frame, text=f"状态: {status}", - anchor="w" + anchor="w", + text_color=status_color ) status_label.pack(fill="x", padx=5, pady=2) + # 显示真实类别(如果有) + true_class = img_info.get('true_class') + if true_class: + true_class_label = ctk.CTkLabel( + info_frame, + text=f"真实类别: {true_class}", + anchor="w", + font=("Arial", 10) + ) + true_class_label.pack(fill="x", padx=5, pady=1) + # 删除按钮 delete_button = ctk.CTkButton( img_frame, @@ -487,13 +539,20 @@ class FoodClassifierApp: predicted_class = self.food_classes[prediction] confidence = np.random.uniform(0.6, 0.95) + # 自动判断识别是否正确 + true_class = img_info.get('true_class') + is_correct = None + if true_class is not None: + is_correct = (predicted_class == true_class) + # 保存结果 result = { 'image_index': i, 'image_name': img_info['name'], 'predicted_class': predicted_class, 'confidence': confidence, - 'is_correct': None # 用户可以手动标记 + 'true_class': true_class, + 'is_correct': is_correct # 自动判断结果 } self.current_results.append(result) @@ -636,59 +695,65 @@ class FoodClassifierApp: ) confidence_label.pack(fill="x", padx=5, pady=2) - # 正确性标记框架 - correct_frame = ctk.CTkFrame(info_frame) - correct_frame.pack(fill="x", padx=5, pady=5) + # 真实类别 + true_class = result.get('true_class') + if true_class is not None: + true_class_label = ctk.CTkLabel( + info_frame, + text=f"真实类别: {true_class}", + anchor="w", + font=("Arial", 11) + ) + true_class_label.pack(fill="x", padx=5, pady=2) - correct_label = ctk.CTkLabel(correct_frame, text="识别是否正确:") - correct_label.pack(side="left", padx=5) - - # 正确按钮 - correct_button = ctk.CTkButton( - correct_frame, - text="正确", - command=lambda idx=i: self.mark_result(idx, True), - width=60, - height=25, - fg_color="green" if result['is_correct'] is True else "gray", - hover_color="darkgreen" - ) - correct_button.pack(side="left", padx=2) - - # 错误按钮 - incorrect_button = ctk.CTkButton( - correct_frame, - text="错误", - command=lambda idx=i: self.mark_result(idx, False), - width=60, - height=25, - fg_color="red" if result['is_correct'] is False else "gray", - hover_color="darkred" - ) - incorrect_button.pack(side="left", padx=2) + # 自动判断结果 + is_correct = result.get('is_correct') + if is_correct is not None: + if is_correct: + status_text = "✓ 识别正确" + status_color = "green" + else: + status_text = "✗ 识别错误" + status_color = "red" + + status_label = ctk.CTkLabel( + info_frame, + text=status_text, + anchor="w", + font=("Arial", 12, "bold"), + text_color=status_color + ) + status_label.pack(fill="x", padx=5, pady=5) + else: + # 如果无法自动判断,显示未知状态 + status_label = ctk.CTkLabel( + info_frame, + text="? 无法自动判断(路径中未包含已知类别)", + anchor="w", + font=("Arial", 11), + text_color="orange" + ) + status_label.pack(fill="x", padx=5, pady=5) - def mark_result(self, result_index, is_correct): - """标记识别结果的正确性""" - if result_index < len(self.current_results): - self.current_results[result_index]['is_correct'] = is_correct - self.update_results_display() - self.update_stats() + def update_stats(self): """更新统计信息""" total_images = len(self.uploaded_images) recognized_images = len(self.current_results) - # 计算准确率 - marked_results = [r for r in self.current_results if r['is_correct'] is not None] - if marked_results: - correct_count = sum(1 for r in marked_results if r['is_correct']) - accuracy = (correct_count / len(marked_results)) * 100 + # 计算准确率(基于自动判断的结果) + auto_judged_results = [r for r in self.current_results if r.get('is_correct') is not None] + if auto_judged_results: + correct_count = sum(1 for r in auto_judged_results if r['is_correct']) + accuracy = (correct_count / len(auto_judged_results)) * 100 + + # 更新统计标签 + stats_text = f"总图片: {total_images} | 已识别: {recognized_images} | 可判断: {len(auto_judged_results)} | 平均准确率: {accuracy:.1f}%" else: - accuracy = 0 + # 如果没有可自动判断的结果 + stats_text = f"总图片: {total_images} | 已识别: {recognized_images} | 可判断: 0 | 平均准确率: 0%" - # 更新统计标签 - stats_text = f"总图片: {total_images} | 已识别: {recognized_images} | 平均准确率: {accuracy:.1f}%" self.stats_label.configure(text=stats_text) def main():