aaappp7878 commited on
Commit
b7211f1
·
verified ·
1 Parent(s): 84e9a1e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +142 -146
app.py CHANGED
@@ -125,7 +125,8 @@ class EnhancedModelManager:
125
  "model_name": model_info["name"],
126
  "ai_probability": ai_probability,
127
  "predicted_class": model_info["model"].config.id2label[predicted_class_idx],
128
- "confidence": float(probabilities[0][predicted_class_idx].item())
 
129
  }
130
 
131
  except Exception as e:
@@ -272,7 +273,6 @@ class EnhancedFeatureExtractor:
272
  self._extract_advanced_features(img_cv, features, image_id)
273
 
274
  return features
275
-
276
  def _extract_color_features(self, img_array, features):
277
  """Extract color-related features"""
278
  if len(img_array.shape) == 3:
@@ -367,7 +367,6 @@ class EnhancedFeatureExtractor:
367
  # 边缘方向一致性 - AI生成图像通常边缘方向过于一致
368
  edge_dir_normalized = edge_dir_hist / np.sum(edge_dir_hist)
369
  features["edge_direction_consistency"] = float(np.max(edge_dir_normalized))
370
-
371
  def _extract_texture_features(self, img_cv, features, image_id):
372
  """Extract texture-related features"""
373
  # 获取灰度图
@@ -476,7 +475,6 @@ class EnhancedFeatureExtractor:
476
  corr_gb = np.corrcoef(noise_g, noise_b)[0,1]
477
 
478
  features["noise_channel_correlation"] = float((abs(corr_rg) + abs(corr_rb) + abs(corr_gb)) / 3)
479
-
480
  def _extract_symmetry_features(self, img_cv, features):
481
  """Extract symmetry-related features"""
482
  h, w = img_cv.shape[:2]
@@ -604,7 +602,6 @@ class EnhancedFeatureExtractor:
604
  features["freq_peak_prominence"] = float(np.mean(radial_mean[peaks]))
605
  except:
606
  pass
607
-
608
  def _extract_advanced_features(self, img_cv, features, image_id):
609
  """Extract advanced features for AI detection"""
610
  # 获取灰度图
@@ -674,99 +671,99 @@ class EnhancedFeatureExtractor:
674
  except:
675
  pass
676
  #############################################
677
- # 特征分析与决策逻辑部分
678
  #############################################
679
 
680
- # 基于图像类型的特征阈值
681
  OPTIMIZED_THRESHOLDS = {
682
  "lbp_entropy": {
683
- "default": 2.0,
684
- "portrait": 1.9,
685
- "landscape": 2.2,
686
  },
687
  "freq_anisotropy": {
688
- "default": 0.008,
689
- "portrait": 0.007,
690
- "landscape": 0.01,
691
  },
692
  "texture_correlation": {
693
- "default": 0.95,
694
- "portrait": 0.92,
695
- "landscape": 0.95,
696
  },
697
  "horizontal_symmetry": {
698
- "default": 0.85,
699
- "portrait": 0.80,
700
- "landscape": 0.85,
701
  },
702
  "vertical_symmetry": {
703
- "default": 0.85,
704
- "portrait": 0.80,
705
- "landscape": 0.85,
706
  },
707
  "noise_spatial_std": {
708
- "default": 0.3,
709
- "portrait": 0.3,
710
- "landscape": 0.4,
711
  },
712
  "freq_ratio": {
713
- "default": 0.05,
714
- "portrait": 0.05,
715
- "landscape": 0.1,
716
  },
717
  "noise_spectrum_std": {
718
- "default": 800,
719
- "portrait": 800,
720
- "landscape": 1000,
721
  },
722
  "color_entropy": {
723
- "default": 3.5,
724
- "portrait": 3.5,
725
- "landscape": 4.0,
726
  },
727
  "lbp_uniformity": {
728
- "default": 0.2,
729
- "portrait": 0.2,
730
- "landscape": 0.15,
731
  },
732
  "noise_channel_correlation": {
733
- "default": 0.5,
734
- "portrait": 0.5,
735
- "landscape": 0.4,
736
  },
737
  "wavelet_h_entropy": {
738
- "default": 3.0,
739
- "portrait": 2.8,
740
- "landscape": 3.2,
741
  },
742
  "dct_entropy": {
743
- "default": 4.0,
744
- "portrait": 3.8,
745
- "landscape": 4.2,
746
  },
747
  "naturalness_index": {
748
- "default": 1.5,
749
- "portrait": 1.3,
750
- "landscape": 1.7,
751
  }
752
  }
753
 
754
- # 特征重要性权重
755
  FEATURE_IMPORTANCE = {
756
- "lbp_entropy": 0.15,
757
- "freq_anisotropy": 0.15,
758
- "texture_correlation": 0.08,
759
- "horizontal_symmetry": 0.03,
760
- "vertical_symmetry": 0.03,
761
- "noise_spatial_std": 0.08,
762
- "freq_ratio": 0.05,
763
- "noise_spectrum_std": 0.05,
764
- "color_entropy": 0.08,
765
- "lbp_uniformity": 0.05,
766
- "noise_channel_correlation": 0.05,
767
- "wavelet_h_entropy": 0.07,
768
- "dct_entropy": 0.08,
769
- "naturalness_index": 0.05
770
  }
771
 
772
  def get_threshold(feature_name, image_type="default"):
@@ -778,7 +775,7 @@ def get_threshold(feature_name, image_type="default"):
778
  OPTIMIZED_THRESHOLDS[feature_name]["default"])
779
 
780
  def check_ai_specific_features(image_features):
781
- """Enhanced check for AI-generated image features"""
782
  ai_score = 0
783
  ai_signs = []
784
 
@@ -804,21 +801,32 @@ def check_ai_specific_features(image_features):
804
  "freq_ratio", "noise_spectrum_std", "color_entropy",
805
  "wavelet_h_entropy", "dct_entropy", "naturalness_index"]:
806
  if value < threshold:
807
- feature_score = min(1.0, (threshold - value) / threshold * 2)
808
- if feature_score > 0.5:
 
809
  ai_signs.append(f"{feature_name} 异常低 ({value:.2f})")
810
 
811
  # 高值表示AI生成的特征
812
  elif feature_name in ["texture_correlation", "horizontal_symmetry", "vertical_symmetry",
813
  "lbp_uniformity", "noise_channel_correlation"]:
814
  if value > threshold:
815
- feature_score = min(1.0, (value - threshold) / (1 - threshold) * 2)
816
- if feature_score > 0.5:
 
817
  ai_signs.append(f"{feature_name} 异常高 ({value:.2f})")
818
 
819
  # 累加加权分数
820
  ai_score += feature_score * importance
821
 
 
 
 
 
 
 
 
 
 
822
  # 计算检测到多少关键特征
823
  critical_count = len(ai_signs)
824
  if critical_count >= 5:
@@ -827,7 +835,6 @@ def check_ai_specific_features(image_features):
827
  ai_score = max(ai_score, 0.6) # 更保守,从0.7改为0.6
828
 
829
  return min(ai_score, 1.0), ai_signs
830
-
831
  def detect_beauty_filter_signs(image_features):
832
  """Detect beauty filter traces"""
833
  beauty_score = 0
@@ -898,6 +905,27 @@ def detect_photoshop_signs(image_features):
898
 
899
  return min(ps_score, 1.0), ps_signs
900
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
901
  def calculate_model_consistency(model_results):
902
  """Calculate the consistency between model predictions"""
903
  if not model_results:
@@ -917,46 +945,33 @@ def calculate_model_consistency(model_results):
917
  consistency = max(0.0, 1.0 - variance * 5) # 缩放以获得合理的一致性分数
918
 
919
  return consistency
920
-
921
  def get_detailed_analysis(ai_probability, ps_score, beauty_score, ps_signs, ai_signs, beauty_signs,
922
  valid_models_count, ai_feature_score, model_consistency):
923
- """Provide detailed analysis with two-level classification and confidence assessment"""
924
 
925
- # 根据模型数量和一致性调整置信度
926
- if model_consistency > 0.8 and valid_models_count >= 2:
927
- confidence_prefix = "极高置信度:"
928
- elif model_consistency > 0.6 and valid_models_count >= 2:
 
929
  confidence_prefix = "高置信度:"
930
- elif valid_models_count >= 1:
 
931
  confidence_prefix = "中等置信度:"
 
932
  else:
933
  confidence_prefix = "低置信度:"
 
934
 
935
  # 计算编辑分数(在所有路径中都需要)
936
  combined_edit_score = max(ps_score, beauty_score)
937
 
938
- # 当模型和特征分析严重不一致时降低置信度
939
- if abs(ai_probability - ai_feature_score) > 0.4:
940
- confidence_prefix = "低置信度:"
941
- explanation = "(模型预测和特征分析结果存在较大差异)"
942
- else:
943
- explanation = ""
944
-
945
- # 处理特征与模型判断不一致的情况
946
- if ai_feature_score > 0.8 and ai_probability > 0.4: # 添加条件
947
- ai_probability = max(ai_probability, 0.7) # 更保守,从0.8改为0.7
948
- category = confidence_prefix + "AI生成图像" + explanation
949
- description = "图像很可能是由AI完全生成,几乎没有真人照片的特征。"
950
- main_category = "AI生成"
951
- elif ai_feature_score > 0.6 and ai_probability > 0.3: # 添加条件
952
- ai_probability = max(ai_probability, 0.6) # 更保守,从0.7改为0.6
953
-
954
- # 第一级分类:AI vs 真实
955
  if ai_probability > 0.6:
956
  category = confidence_prefix + "AI生成图像" + explanation
957
  description = "图像很可能是由AI完全生成,几乎没有真人照片的特征。"
958
  main_category = "AI生成"
959
- else:
960
  # 第二级分类:素人 vs 修图
961
  if combined_edit_score > 0.5:
962
  category = confidence_prefix + "真人照片,修图痕迹明显" + explanation
@@ -966,15 +981,14 @@ def get_detailed_analysis(ai_probability, ps_score, beauty_score, ps_signs, ai_s
966
  category = confidence_prefix + "真实素人照片" + explanation
967
  description = "图像很可能是未经大量处理的真人照片,保留了自然的细节和特征。"
968
  main_category = "真人照片-素人"
969
-
970
- # 处理边界情况 - 添加"不确定"类别
971
- if 0.4 < ai_probability < 0.6 and abs(ai_probability - ai_feature_score) > 0.3:
972
- category = "无法确定" + explanation
973
  description = "系统无法确定该图像是AI生成还是真实照片。模型预测和特征分析结果不一致,需要人工判断。"
974
  main_category = "无法确定"
975
 
976
  # 处理边界情况 - AI生成与高度修图
977
- elif ai_probability > 0.45 and combined_edit_score > 0.7:
978
  category = confidence_prefix + "真人照片,修图痕迹明显(也可能是AI生成)" + explanation
979
  description = "图像可能是真人照片经过大量后期处理,也可能是AI生成图像。由于现代AI技术与高度修图效果相似,难以完全区分。"
980
  main_category = "真人照片-修图明显"
@@ -985,8 +999,9 @@ def get_detailed_analysis(ai_probability, ps_score, beauty_score, ps_signs, ai_s
985
  beauty_details = "检测到的美颜特征:" + "、".join(beauty_signs) if beauty_signs else "未检测到明显的美颜特征。"
986
 
987
  return category, description, ps_details, ai_details, beauty_details, main_category
 
988
  def detect_ai_image(image):
989
- """Enhanced main detection function with two-stage detection and improved decision logic"""
990
  if image is None:
991
  return {"error": "未提供图像"}
992
 
@@ -1020,6 +1035,9 @@ def detect_ai_image(image):
1020
  model_result = model_manager.get_model_prediction(key, image)
1021
 
1022
  if model_result and "error" not in model_result:
 
 
 
1023
  results[key] = model_result
1024
  weighted_ai_probability += model_result["ai_probability"] * model_info["weight"]
1025
  valid_models += 1
@@ -1042,51 +1060,29 @@ def detect_ai_image(image):
1042
  ps_score, ps_signs = detect_photoshop_signs(image_features)
1043
  beauty_score, beauty_signs = detect_beauty_filter_signs(image_features)
1044
 
1045
- # 协同决策:结合模型预测和特征分析
1046
- adjusted_probability = final_ai_probability
1047
 
1048
- # 根据模型一致性调整特征分析的影响
1049
- if model_consistency > 0.7:
1050
- # 模型一致性高,增加模型预测的权重
1051
- if ai_feature_score > 0.8 and final_ai_probability > 0.4:
1052
- adjusted_probability = 0.7 * final_ai_probability + 0.3 * ai_feature_score
1053
- elif ai_feature_score > 0.6 and final_ai_probability > 0.3:
1054
- adjusted_probability = 0.6 * final_ai_probability + 0.4 * ai_feature_score
1055
- else:
1056
- adjusted_probability = 0.8 * final_ai_probability + 0.2 * ai_feature_score
1057
- else:
1058
- # 模型一致性低,增加特征分析的权重
1059
- if ai_feature_score > 0.8 and final_ai_probability > 0.4:
1060
- adjusted_probability = 0.4 * final_ai_probability + 0.6 * ai_feature_score
1061
- elif ai_feature_score > 0.6 and final_ai_probability > 0.3:
1062
- adjusted_probability = 0.5 * final_ai_probability + 0.5 * ai_feature_score
1063
- else:
1064
- adjusted_probability = 0.6 * final_ai_probability + 0.4 * ai_feature_score
1065
 
1066
- # 检查关键特征
1067
- key_ai_features_count = 0
1068
-
1069
- # LBP熵(微观纹理分析)
1070
- if "lbp_entropy" in image_features:
1071
- threshold = get_threshold("lbp_entropy", image_features.get("image_type", "default"))
1072
- if image_features["lbp_entropy"] < threshold:
1073
- key_ai_features_count += 1
1074
-
1075
- # 频率各向异性
1076
- if "freq_anisotropy" in image_features:
1077
- threshold = get_threshold("freq_anisotropy", image_features.get("image_type", "default"))
1078
- if image_features["freq_anisotropy"] < threshold:
1079
- key_ai_features_count += 1
1080
-
1081
- # 小波熵
1082
- if "wavelet_h_entropy" in image_features:
1083
- threshold = get_threshold("wavelet_h_entropy", image_features.get("image_type", "default"))
1084
- if image_features["wavelet_h_entropy"] < threshold:
1085
- key_ai_features_count += 1
1086
 
1087
- # 多个关键特征强烈表明AI生成,但需要模型支持
1088
- if key_ai_features_count >= 2 and final_ai_probability > 0.3:
1089
- adjusted_probability = max(adjusted_probability, 0.6) # 更保守,从0.7改为0.6
 
 
 
1090
 
1091
  # 确保概率在有效范围内
1092
  adjusted_probability = min(1.0, max(0.0, adjusted_probability))
@@ -1094,7 +1090,7 @@ def detect_ai_image(image):
1094
  # 获取详细分析
1095
  category, description, ps_details, ai_details, beauty_details, main_category = get_detailed_analysis(
1096
  adjusted_probability, ps_score, beauty_score, ps_signs, ai_signs, beauty_signs,
1097
- valid_models, ai_feature_score, model_consistency
1098
  )
1099
 
1100
  # 构建最终结果
@@ -1106,7 +1102,8 @@ def detect_ai_image(image):
1106
  "original_ai_probability": final_ai_probability,
1107
  "ps_score": ps_score,
1108
  "beauty_score": beauty_score,
1109
- "ai_feature_score": ai_feature_score,
 
1110
  "model_consistency": model_consistency,
1111
  "category": category,
1112
  "main_category": main_category,
@@ -1130,7 +1127,6 @@ def detect_ai_image(image):
1130
  # 返回两个值:JSON结果和标签数据
1131
  label_data = {main_category: 1.0}
1132
  return final_result, label_data
1133
-
1134
  def save_user_feedback(image_id, user_feedback):
1135
  """Save user feedback for continuous learning"""
1136
  if not image_id:
 
125
  "model_name": model_info["name"],
126
  "ai_probability": ai_probability,
127
  "predicted_class": model_info["model"].config.id2label[predicted_class_idx],
128
+ "confidence": float(probabilities[0][predicted_class_idx].item()),
129
+ "raw_probability": ai_probability # 保存原始概率用于校准
130
  }
131
 
132
  except Exception as e:
 
273
  self._extract_advanced_features(img_cv, features, image_id)
274
 
275
  return features
 
276
  def _extract_color_features(self, img_array, features):
277
  """Extract color-related features"""
278
  if len(img_array.shape) == 3:
 
367
  # 边缘方向一致性 - AI生成图像通常边缘方向过于一致
368
  edge_dir_normalized = edge_dir_hist / np.sum(edge_dir_hist)
369
  features["edge_direction_consistency"] = float(np.max(edge_dir_normalized))
 
370
  def _extract_texture_features(self, img_cv, features, image_id):
371
  """Extract texture-related features"""
372
  # 获取灰度图
 
475
  corr_gb = np.corrcoef(noise_g, noise_b)[0,1]
476
 
477
  features["noise_channel_correlation"] = float((abs(corr_rg) + abs(corr_rb) + abs(corr_gb)) / 3)
 
478
  def _extract_symmetry_features(self, img_cv, features):
479
  """Extract symmetry-related features"""
480
  h, w = img_cv.shape[:2]
 
602
  features["freq_peak_prominence"] = float(np.mean(radial_mean[peaks]))
603
  except:
604
  pass
 
605
  def _extract_advanced_features(self, img_cv, features, image_id):
606
  """Extract advanced features for AI detection"""
607
  # 获取灰度图
 
671
  except:
672
  pass
673
  #############################################
674
+ # 特征分析与决策逻辑部分 - 重新调整
675
  #############################################
676
 
677
+ # 基于图像类型的特征阈值 - 更严格的阈值
678
  OPTIMIZED_THRESHOLDS = {
679
  "lbp_entropy": {
680
+ "default": 1.8, # 更严格的阈值
681
+ "portrait": 1.7,
682
+ "landscape": 1.9,
683
  },
684
  "freq_anisotropy": {
685
+ "default": 0.005, # 更严格的阈值
686
+ "portrait": 0.004,
687
+ "landscape": 0.006,
688
  },
689
  "texture_correlation": {
690
+ "default": 0.97, # 更严格的阈值
691
+ "portrait": 0.96,
692
+ "landscape": 0.97,
693
  },
694
  "horizontal_symmetry": {
695
+ "default": 0.9, # 更严格的阈值
696
+ "portrait": 0.88,
697
+ "landscape": 0.9,
698
  },
699
  "vertical_symmetry": {
700
+ "default": 0.9, # 更严格的阈值
701
+ "portrait": 0.88,
702
+ "landscape": 0.9,
703
  },
704
  "noise_spatial_std": {
705
+ "default": 0.2, # 更严格的阈值
706
+ "portrait": 0.2,
707
+ "landscape": 0.25,
708
  },
709
  "freq_ratio": {
710
+ "default": 0.0, # 更严格的阈值
711
+ "portrait": -0.05,
712
+ "landscape": 0.0,
713
  },
714
  "noise_spectrum_std": {
715
+ "default": 600, # 更严格的阈值
716
+ "portrait": 600,
717
+ "landscape": 700,
718
  },
719
  "color_entropy": {
720
+ "default": 3.0, # 更严格的阈值
721
+ "portrait": 3.0,
722
+ "landscape": 3.2,
723
  },
724
  "lbp_uniformity": {
725
+ "default": 0.25, # 更严格的阈值
726
+ "portrait": 0.25,
727
+ "landscape": 0.2,
728
  },
729
  "noise_channel_correlation": {
730
+ "default": 0.97, # 更严格的阈值
731
+ "portrait": 0.97,
732
+ "landscape": 0.95,
733
  },
734
  "wavelet_h_entropy": {
735
+ "default": 1.5, # 更严格的阈值
736
+ "portrait": 1.4,
737
+ "landscape": 1.6,
738
  },
739
  "dct_entropy": {
740
+ "default": 0.005, # 更严格的阈值
741
+ "portrait": 0.004,
742
+ "landscape": 0.006,
743
  },
744
  "naturalness_index": {
745
+ "default": 0.6, # 更严格的阈值
746
+ "portrait": 0.55,
747
+ "landscape": 0.65,
748
  }
749
  }
750
 
751
+ # 特征重要性权重 - 调整权重
752
  FEATURE_IMPORTANCE = {
753
+ "lbp_entropy": 0.12,
754
+ "freq_anisotropy": 0.12,
755
+ "texture_correlation": 0.06,
756
+ "horizontal_symmetry": 0.02,
757
+ "vertical_symmetry": 0.02,
758
+ "noise_spatial_std": 0.06,
759
+ "freq_ratio": 0.04,
760
+ "noise_spectrum_std": 0.04,
761
+ "color_entropy": 0.06,
762
+ "lbp_uniformity": 0.04,
763
+ "noise_channel_correlation": 0.12, # 增加权重
764
+ "wavelet_h_entropy": 0.12, # 增加权重
765
+ "dct_entropy": 0.12, # 增加权重
766
+ "naturalness_index": 0.06
767
  }
768
 
769
  def get_threshold(feature_name, image_type="default"):
 
775
  OPTIMIZED_THRESHOLDS[feature_name]["default"])
776
 
777
  def check_ai_specific_features(image_features):
778
+ """Enhanced check for AI-generated image features with stricter criteria"""
779
  ai_score = 0
780
  ai_signs = []
781
 
 
801
  "freq_ratio", "noise_spectrum_std", "color_entropy",
802
  "wavelet_h_entropy", "dct_entropy", "naturalness_index"]:
803
  if value < threshold:
804
+ # 更严格的评分,只有显著低于阈值才给高分
805
+ feature_score = min(1.0, (threshold - value) / threshold * 1.5)
806
+ if feature_score > 0.7: # 提高显著性阈值
807
  ai_signs.append(f"{feature_name} 异常低 ({value:.2f})")
808
 
809
  # 高值表示AI生成的特征
810
  elif feature_name in ["texture_correlation", "horizontal_symmetry", "vertical_symmetry",
811
  "lbp_uniformity", "noise_channel_correlation"]:
812
  if value > threshold:
813
+ # 更严格的评分,只有显著高于阈值才给高分
814
+ feature_score = min(1.0, (value - threshold) / (1 - threshold) * 1.5)
815
+ if feature_score > 0.7: # 提高显著性阈值
816
  ai_signs.append(f"{feature_name} 异常高 ({value:.2f})")
817
 
818
  # 累加加权分数
819
  ai_score += feature_score * importance
820
 
821
+ # 特征组合分析 - 检查特定组合模式
822
+ if ("dct_entropy" in image_features and image_features["dct_entropy"] < 0.005 and
823
+ "wavelet_h_entropy" in image_features and image_features["wavelet_h_entropy"] < 1.5 and
824
+ "noise_channel_correlation" in image_features and image_features["noise_channel_correlation"] > 0.97):
825
+ # 这种组合强烈表明是AI生成
826
+ ai_score = max(ai_score, 0.9)
827
+ if "特征组合模式" not in ai_signs:
828
+ ai_signs.append("特征组合模式: 多个关键特征同时异常")
829
+
830
  # 计算检测到多少关键特征
831
  critical_count = len(ai_signs)
832
  if critical_count >= 5:
 
835
  ai_score = max(ai_score, 0.6) # 更保守,从0.7改为0.6
836
 
837
  return min(ai_score, 1.0), ai_signs
 
838
  def detect_beauty_filter_signs(image_features):
839
  """Detect beauty filter traces"""
840
  beauty_score = 0
 
905
 
906
  return min(ps_score, 1.0), ps_signs
907
 
908
+ def calibrate_model_output(probability):
909
+ """校准模型输出,解决模型偏向真人的问题"""
910
+ # 如果模型输出总是在0.3-0.4之间,我们可以拉伸这个范围
911
+ if 0.25 <= probability <= 0.4:
912
+ # 将0.25-0.4范围拉伸到0.1-0.9
913
+ return 0.1 + (probability - 0.25) * (0.9 - 0.1) / (0.4 - 0.25)
914
+ return probability
915
+
916
+ def calibrate_feature_score(score, signs):
917
+ """校准特征分析分数,解决特征分析偏向AI的问题"""
918
+ # 如果特征分数高但检测到的特征少,降低分数
919
+ if score > 0.7 and len(signs) < 3:
920
+ return 0.5 + (score - 0.5) * 0.5 # 降低分数
921
+ # 如果特征分数高且检测到多个特征,保持高分
922
+ elif score > 0.7 and len(signs) >= 4:
923
+ return score
924
+ # 中等分数情况
925
+ elif 0.4 < score <= 0.7:
926
+ return 0.4 + (score - 0.4) * 0.7 # 略微降低
927
+ return score
928
+
929
  def calculate_model_consistency(model_results):
930
  """Calculate the consistency between model predictions"""
931
  if not model_results:
 
945
  consistency = max(0.0, 1.0 - variance * 5) # 缩放以获得合理的一致性分数
946
 
947
  return consistency
 
948
  def get_detailed_analysis(ai_probability, ps_score, beauty_score, ps_signs, ai_signs, beauty_signs,
949
  valid_models_count, ai_feature_score, model_consistency):
950
+ """Provide detailed analysis with improved confidence assessment"""
951
 
952
+ # 根据模型和特征分析的一致性调整置信度
953
+ if abs(ai_probability - ai_feature_score) > 0.2:
954
+ confidence_prefix = "低置信度:"
955
+ explanation = "(模型预测和特征分析结果存在较大差异)"
956
+ elif model_consistency > 0.8 and valid_models_count >= 2:
957
  confidence_prefix = "高置信度:"
958
+ explanation = ""
959
+ elif model_consistency > 0.6 and valid_models_count >= 2:
960
  confidence_prefix = "中等置信度:"
961
+ explanation = ""
962
  else:
963
  confidence_prefix = "低置信度:"
964
+ explanation = ""
965
 
966
  # 计算编辑分数(在所有路径中都需要)
967
  combined_edit_score = max(ps_score, beauty_score)
968
 
969
+ # 分类逻辑 - 从中立起点开始
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970
  if ai_probability > 0.6:
971
  category = confidence_prefix + "AI生成图像" + explanation
972
  description = "图像很可能是由AI完全生成,几乎没有真人照片的特征。"
973
  main_category = "AI生成"
974
+ elif ai_probability < 0.4:
975
  # 第二级分类:素人 vs 修图
976
  if combined_edit_score > 0.5:
977
  category = confidence_prefix + "真人照片,修图痕迹明显" + explanation
 
981
  category = confidence_prefix + "真实素人照片" + explanation
982
  description = "图像很可能是未经大量处理的真人照片,保留了自然的细节和特征。"
983
  main_category = "真人照片-素人"
984
+ else:
985
+ # 处理边界情况 - 添加"无法确定"类别
986
+ category = confidence_prefix + "无法确定" + explanation
 
987
  description = "系统无法确定该图像是AI生成还是真实照片。模型预测和特征分析结果不一致,需要人工判断。"
988
  main_category = "无法确定"
989
 
990
  # 处理边界情况 - AI生成与高度修图
991
+ if 0.45 < ai_probability < 0.55 and combined_edit_score > 0.7:
992
  category = confidence_prefix + "真人照片,修图痕迹明显(也可能是AI生成)" + explanation
993
  description = "图像可能是真人照片经过大量后期处理,也可能是AI生成图像。由于现代AI技术与高度修图效果相似,难以完全区分。"
994
  main_category = "真人照片-修图明显"
 
999
  beauty_details = "检测到的美颜特征:" + "、".join(beauty_signs) if beauty_signs else "未检测到明显的美颜特征。"
1000
 
1001
  return category, description, ps_details, ai_details, beauty_details, main_category
1002
+
1003
  def detect_ai_image(image):
1004
+ """Enhanced main detection function with improved decision logic"""
1005
  if image is None:
1006
  return {"error": "未提供图像"}
1007
 
 
1035
  model_result = model_manager.get_model_prediction(key, image)
1036
 
1037
  if model_result and "error" not in model_result:
1038
+ # 校准模型输出
1039
+ model_result["ai_probability"] = calibrate_model_output(model_result["ai_probability"])
1040
+
1041
  results[key] = model_result
1042
  weighted_ai_probability += model_result["ai_probability"] * model_info["weight"]
1043
  valid_models += 1
 
1060
  ps_score, ps_signs = detect_photoshop_signs(image_features)
1061
  beauty_score, beauty_signs = detect_beauty_filter_signs(image_features)
1062
 
1063
+ # 校准特征分析分数
1064
+ calibrated_feature_score = calibrate_feature_score(ai_feature_score, ai_signs)
1065
 
1066
+ # 从中立起点开始决策
1067
+ adjusted_probability = 0.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1068
 
1069
+ # 根据校准后的模型和特征分析调整概率
1070
+ if final_ai_probability > 0.7 or calibrated_feature_score > 0.8:
1071
+ # 强AI证据
1072
+ adjusted_probability = 0.5 + (final_ai_probability * 0.25 + calibrated_feature_score * 0.25)
1073
+ elif final_ai_probability < 0.3 and calibrated_feature_score < 0.3:
1074
+ # 强真人证据
1075
+ adjusted_probability = 0.5 - ((0.3 - final_ai_probability) * 0.25 + (0.3 - calibrated_feature_score) * 0.25)
1076
+ else:
1077
+ # 证据不足,保持在中间区域
1078
+ adjusted_probability = 0.5 + (final_ai_probability - 0.5) * 0.2 + (calibrated_feature_score - 0.5) * 0.2
 
 
 
 
 
 
 
 
 
 
1079
 
1080
+ # 特征组合分析 - 强有力的组合证据
1081
+ if ("dct_entropy" in image_features and image_features["dct_entropy"] < 0.005 and
1082
+ "wavelet_h_entropy" in image_features and image_features["wavelet_h_entropy"] < 1.5 and
1083
+ "noise_channel_correlation" in image_features and image_features["noise_channel_correlation"] > 0.97):
1084
+ # 这种组合强烈表明是AI生成
1085
+ adjusted_probability = max(adjusted_probability, 0.7)
1086
 
1087
  # 确保概率在有效范围内
1088
  adjusted_probability = min(1.0, max(0.0, adjusted_probability))
 
1090
  # 获取详细分析
1091
  category, description, ps_details, ai_details, beauty_details, main_category = get_detailed_analysis(
1092
  adjusted_probability, ps_score, beauty_score, ps_signs, ai_signs, beauty_signs,
1093
+ valid_models, calibrated_feature_score, model_consistency
1094
  )
1095
 
1096
  # 构建最终结果
 
1102
  "original_ai_probability": final_ai_probability,
1103
  "ps_score": ps_score,
1104
  "beauty_score": beauty_score,
1105
+ "ai_feature_score": calibrated_feature_score,
1106
+ "raw_feature_score": ai_feature_score,
1107
  "model_consistency": model_consistency,
1108
  "category": category,
1109
  "main_category": main_category,
 
1127
  # 返回两个值:JSON结果和标签数据
1128
  label_data = {main_category: 1.0}
1129
  return final_result, label_data
 
1130
  def save_user_feedback(image_id, user_feedback):
1131
  """Save user feedback for continuous learning"""
1132
  if not image_id: