Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -38,6 +38,10 @@ for key in models:
|
|
38 |
models[key]["processor"] = None
|
39 |
models[key]["model"] = None
|
40 |
|
|
|
|
|
|
|
|
|
41 |
def process_model_output(model_info, outputs, probabilities):
|
42 |
"""处理不同模型的输出,统一返回AI生成概率"""
|
43 |
model_name = model_info["name"].lower()
|
@@ -56,16 +60,16 @@ def process_model_output(model_info, outputs, probabilities):
|
|
56 |
if "human" in label_lower or "real" in label_lower:
|
57 |
human_label_idx = idx
|
58 |
|
59 |
-
#
|
60 |
if human_label_idx is not None:
|
61 |
-
#
|
62 |
-
ai_probability = float(probabilities[0][human_label_idx].item())
|
63 |
elif ai_label_idx is not None:
|
64 |
-
#
|
65 |
ai_probability = float(probabilities[0][ai_label_idx].item())
|
66 |
else:
|
67 |
-
#
|
68 |
-
ai_probability =
|
69 |
|
70 |
elif "resnet" in model_name:
|
71 |
# 通用图像分类模型,使用简单启发式方法
|
@@ -108,6 +112,10 @@ def process_model_output(model_info, outputs, probabilities):
|
|
108 |
|
109 |
return ai_probability
|
110 |
|
|
|
|
|
|
|
|
|
111 |
def analyze_image_features(image):
|
112 |
"""分析图像特征"""
|
113 |
# 转换为OpenCV格式
|
@@ -203,6 +211,56 @@ def analyze_image_features(image):
|
|
203 |
|
204 |
return features
|
205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
def detect_photoshop_signs(image_features):
|
207 |
"""检测图像中的PS痕迹"""
|
208 |
ps_score = 0
|
@@ -254,16 +312,13 @@ def detect_photoshop_signs(image_features):
|
|
254 |
ps_score += 0.2
|
255 |
ps_signs.append("频率分布不自然,可能有过度锐化处理")
|
256 |
|
257 |
-
# 检查对称性不自然
|
258 |
-
if "horizontal_symmetry" in image_features and "vertical_symmetry" in image_features:
|
259 |
-
avg_symmetry = (image_features["horizontal_symmetry"] + image_features["vertical_symmetry"]) / 2
|
260 |
-
if avg_symmetry > 0.8:
|
261 |
-
ps_score += 0.2
|
262 |
-
ps_signs.append("图像对称性过高,可能经过对称处理")
|
263 |
-
|
264 |
return min(ps_score, 1.0), ps_signs
|
265 |
|
266 |
-
|
|
|
|
|
|
|
|
|
267 |
"""提供更详细的分析结果"""
|
268 |
|
269 |
# 根据有效模型数量调整置信度描述
|
@@ -275,17 +330,18 @@ def get_detailed_analysis(ai_probability, ps_score, ps_signs, valid_models_count
|
|
275 |
elif valid_models_count == 1:
|
276 |
confidence_prefix = "中等置信度:"
|
277 |
|
278 |
-
|
|
|
279 |
category = confidence_prefix + "高概率AI生成"
|
280 |
-
description = "
|
281 |
-
elif ai_probability > 0.
|
282 |
if ps_score > 0.5:
|
283 |
category = confidence_prefix + "中等概率AI生成,高概率PS修图"
|
284 |
description = "图像可能是真人照片经过大量后期处理,或是AI生成后经过修饰的图像。"
|
285 |
else:
|
286 |
category = confidence_prefix + "中等概率AI生成"
|
287 |
description = "图像有较多AI生成的特征,但也保留了一些真实照片的特点。"
|
288 |
-
elif ai_probability > 0.
|
289 |
if ps_score > 0.5:
|
290 |
category = confidence_prefix + "低概率AI生成,高概率PS修图"
|
291 |
description = "图像更可能是真人照片经过大量后期处理,PS痕迹明显。"
|
@@ -312,8 +368,18 @@ def get_detailed_analysis(ai_probability, ps_score, ps_signs, valid_models_count
|
|
312 |
else:
|
313 |
ps_details = "未检测到明显的修图痕迹。"
|
314 |
|
315 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
316 |
|
|
|
|
|
|
|
317 |
def detect_ai_image(image):
|
318 |
"""主检测函数"""
|
319 |
if image is None:
|
@@ -365,47 +431,70 @@ def detect_ai_image(image):
|
|
365 |
# 分析图像特征
|
366 |
image_features = analyze_image_features(image)
|
367 |
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
# 应用特征权重调整AI概率
|
369 |
adjusted_probability = final_ai_probability
|
370 |
|
371 |
-
#
|
372 |
-
if
|
373 |
-
adjusted_probability
|
|
|
|
|
374 |
|
375 |
-
#
|
376 |
-
if "
|
377 |
-
adjusted_probability += 0.
|
|
|
|
|
378 |
|
379 |
-
#
|
380 |
-
if image_features["
|
381 |
adjusted_probability += 0.1
|
382 |
|
383 |
-
#
|
384 |
-
if
|
385 |
adjusted_probability += 0.1
|
386 |
|
387 |
# 确保概率在0-1范围内
|
388 |
adjusted_probability = min(1.0, max(0.0, adjusted_probability))
|
389 |
|
390 |
-
#
|
391 |
-
|
|
|
|
|
|
|
|
|
392 |
|
393 |
# 获取详细分析
|
394 |
-
category, description, ps_details = get_detailed_analysis(
|
|
|
|
|
395 |
|
396 |
# 构建最终结果
|
397 |
final_result = {
|
398 |
"ai_probability": adjusted_probability,
|
|
|
399 |
"ps_score": ps_score,
|
|
|
400 |
"category": category,
|
401 |
"description": description,
|
402 |
"ps_details": ps_details,
|
|
|
403 |
"individual_model_results": results,
|
404 |
"features": image_features
|
405 |
}
|
406 |
|
407 |
return final_result
|
408 |
|
|
|
|
|
|
|
|
|
409 |
# 创建Gradio界面
|
410 |
iface = gr.Interface(
|
411 |
fn=detect_ai_image,
|
|
|
38 |
models[key]["processor"] = None
|
39 |
models[key]["model"] = None
|
40 |
|
41 |
+
|
42 |
+
## 2. 模型输出处理
|
43 |
+
|
44 |
+
python
|
45 |
def process_model_output(model_info, outputs, probabilities):
|
46 |
"""处理不同模型的输出,统一返回AI生成概率"""
|
47 |
model_name = model_info["name"].lower()
|
|
|
60 |
if "human" in label_lower or "real" in label_lower:
|
61 |
human_label_idx = idx
|
62 |
|
63 |
+
# 修正后的标签解释逻辑
|
64 |
if human_label_idx is not None:
|
65 |
+
# 如果预测为human,则AI概率应该低
|
66 |
+
ai_probability = 1 - float(probabilities[0][human_label_idx].item())
|
67 |
elif ai_label_idx is not None:
|
68 |
+
# 如果预测为AI,则AI概率应该高
|
69 |
ai_probability = float(probabilities[0][ai_label_idx].item())
|
70 |
else:
|
71 |
+
# 默认情况
|
72 |
+
ai_probability = 0.5
|
73 |
|
74 |
elif "resnet" in model_name:
|
75 |
# 通用图像分类模型,使用简单启发式方法
|
|
|
112 |
|
113 |
return ai_probability
|
114 |
|
115 |
+
|
116 |
+
## 3. 图像特征分析
|
117 |
+
|
118 |
+
python
|
119 |
def analyze_image_features(image):
|
120 |
"""分析图像特征"""
|
121 |
# 转换为OpenCV格式
|
|
|
211 |
|
212 |
return features
|
213 |
|
214 |
+
|
215 |
+
## 4. AI特征检查
|
216 |
+
|
217 |
+
python
|
218 |
+
def check_ai_specific_features(image_features):
|
219 |
+
"""检查AI生成图像的典型特征"""
|
220 |
+
ai_score = 0
|
221 |
+
ai_signs = []
|
222 |
+
|
223 |
+
# 检查对称性 - AI生成图像通常对称性高
|
224 |
+
if "horizontal_symmetry" in image_features and "vertical_symmetry" in image_features:
|
225 |
+
avg_symmetry = (image_features["horizontal_symmetry"] + image_features["vertical_symmetry"]) / 2
|
226 |
+
if avg_symmetry > 0.7:
|
227 |
+
ai_score += 0.3
|
228 |
+
ai_signs.append("图像对称性异常高")
|
229 |
+
|
230 |
+
# 检查纹理相关性 - AI生成图像通常纹理相关性高
|
231 |
+
if "texture_correlation" in image_features and image_features["texture_correlation"] > 0.9:
|
232 |
+
ai_score += 0.2
|
233 |
+
ai_signs.append("纹理相关性异常高")
|
234 |
+
|
235 |
+
# 检查边缘与噪声的关系 - AI生成图像通常边缘清晰但噪声不自然
|
236 |
+
if "edge_density" in image_features and "noise_level" in image_features:
|
237 |
+
edge_noise_ratio = image_features["edge_density"] / max(image_features["noise_level"], 0.001)
|
238 |
+
if edge_noise_ratio < 0.01:
|
239 |
+
ai_score += 0.2
|
240 |
+
ai_signs.append("边缘与噪声分布不自然")
|
241 |
+
|
242 |
+
# 检查颜色平滑度 - AI生成图像通常颜色过渡更平滑
|
243 |
+
if "color_std" in image_features and image_features["color_std"] < 10:
|
244 |
+
ai_score += 0.2
|
245 |
+
ai_signs.append("颜色过渡异常平滑")
|
246 |
+
|
247 |
+
# 检查纹理能量 - AI生成图像通常纹理能量分布不自然
|
248 |
+
if "texture_energy" in image_features and image_features["texture_energy"] < 0.02:
|
249 |
+
ai_score += 0.2
|
250 |
+
ai_signs.append("纹理能量分布不自然")
|
251 |
+
|
252 |
+
# 检查频率比例 - AI生成图像通常频率分布不自然
|
253 |
+
if "freq_ratio" in image_features:
|
254 |
+
if image_features["freq_ratio"] < 0.1 or image_features["freq_ratio"] > 2.0:
|
255 |
+
ai_score += 0.2
|
256 |
+
ai_signs.append("频率分布不自然")
|
257 |
+
|
258 |
+
return min(ai_score, 1.0), ai_signs
|
259 |
+
|
260 |
+
|
261 |
+
## 5. PS痕迹检测
|
262 |
+
|
263 |
+
python
|
264 |
def detect_photoshop_signs(image_features):
|
265 |
"""检测图像中的PS痕迹"""
|
266 |
ps_score = 0
|
|
|
312 |
ps_score += 0.2
|
313 |
ps_signs.append("频率分布不自然,可能有过度锐化处理")
|
314 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
return min(ps_score, 1.0), ps_signs
|
316 |
|
317 |
+
|
318 |
+
## 6. 结果分析与分类
|
319 |
+
|
320 |
+
python
|
321 |
+
def get_detailed_analysis(ai_probability, ps_score, ps_signs, ai_signs, valid_models_count):
|
322 |
"""提供更详细的分析结果"""
|
323 |
|
324 |
# 根据有效模型数量调整置信度描述
|
|
|
330 |
elif valid_models_count == 1:
|
331 |
confidence_prefix = "中等置信度:"
|
332 |
|
333 |
+
# 调整后的阈值判断
|
334 |
+
if ai_probability > 0.6: # 降低为0.6
|
335 |
category = confidence_prefix + "高概率AI生成"
|
336 |
+
description = "图像很可能是由AI完全生成,几乎没有真人照片的特征。"
|
337 |
+
elif ai_probability > 0.4: # 降低为0.4
|
338 |
if ps_score > 0.5:
|
339 |
category = confidence_prefix + "中等概率AI生成,高概率PS修图"
|
340 |
description = "图像可能是真人照片经过大量后期处理,或是AI生成后经过修饰的图像。"
|
341 |
else:
|
342 |
category = confidence_prefix + "中等概率AI生成"
|
343 |
description = "图像有较多AI生成的特征,但也保留了一些真实照片的特点。"
|
344 |
+
elif ai_probability > 0.3: # 降低为0.3
|
345 |
if ps_score > 0.5:
|
346 |
category = confidence_prefix + "低概率AI生成,高概率PS修图"
|
347 |
description = "图像更可能是真人照片经过大量后期处理,PS痕迹明显。"
|
|
|
368 |
else:
|
369 |
ps_details = "未检测到明显的修图痕迹。"
|
370 |
|
371 |
+
# 添加AI特征描述
|
372 |
+
if ai_signs:
|
373 |
+
ai_details = "检测到的AI特征:" + "、".join(ai_signs)
|
374 |
+
else:
|
375 |
+
ai_details = "未检测到明显的AI生成特征。"
|
376 |
+
|
377 |
+
return category, description, ps_details, ai_details
|
378 |
+
|
379 |
|
380 |
+
## 7. 主检测函数
|
381 |
+
|
382 |
+
python
|
383 |
def detect_ai_image(image):
|
384 |
"""主检测函数"""
|
385 |
if image is None:
|
|
|
431 |
# 分析图像特征
|
432 |
image_features = analyze_image_features(image)
|
433 |
|
434 |
+
# 检查AI特定特征
|
435 |
+
ai_feature_score, ai_signs = check_ai_specific_features(image_features)
|
436 |
+
|
437 |
+
# 分析PS痕迹
|
438 |
+
ps_score, ps_signs = detect_photoshop_signs(image_features)
|
439 |
+
|
440 |
# 应用特征权重调整AI概率
|
441 |
adjusted_probability = final_ai_probability
|
442 |
|
443 |
+
# 如果AI特征分数高,大幅提高AI概率
|
444 |
+
if ai_feature_score > 0.5:
|
445 |
+
adjusted_probability = max(adjusted_probability, 0.7)
|
446 |
+
elif ai_feature_score > 0.3:
|
447 |
+
adjusted_probability = max(adjusted_probability, 0.5)
|
448 |
|
449 |
+
# 高对称性是AI生成的强烈指标
|
450 |
+
if "horizontal_symmetry" in image_features and image_features["horizontal_symmetry"] > 0.7:
|
451 |
+
adjusted_probability += 0.15
|
452 |
+
if "vertical_symmetry" in image_features and image_features["vertical_symmetry"] > 0.7:
|
453 |
+
adjusted_probability += 0.15
|
454 |
|
455 |
+
# 高纹理相关性通常表示AI生成
|
456 |
+
if "texture_correlation" in image_features and image_features["texture_correlation"] > 0.9:
|
457 |
adjusted_probability += 0.1
|
458 |
|
459 |
+
# 低边缘密度通常表示AI生成
|
460 |
+
if image_features["edge_density"] < 0.01:
|
461 |
adjusted_probability += 0.1
|
462 |
|
463 |
# 确保概率在0-1范围内
|
464 |
adjusted_probability = min(1.0, max(0.0, adjusted_probability))
|
465 |
|
466 |
+
# 如果umm-maybe/AI-image-detector模型的预测与其他模型不一致,增加其权重
|
467 |
+
if "model1" in results and "ai_probability" in results["model1"]:
|
468 |
+
ai_detector_prob = results["model1"]["ai_probability"]
|
469 |
+
# 如果专用AI检测器给出的概率与调整后概率差异大,增加其权重
|
470 |
+
if abs(ai_detector_prob - adjusted_probability) > 0.3:
|
471 |
+
adjusted_probability = (adjusted_probability + ai_detector_prob * 2) / 3
|
472 |
|
473 |
# 获取详细分析
|
474 |
+
category, description, ps_details, ai_details = get_detailed_analysis(
|
475 |
+
adjusted_probability, ps_score, ps_signs, ai_signs, valid_models
|
476 |
+
)
|
477 |
|
478 |
# 构建最终结果
|
479 |
final_result = {
|
480 |
"ai_probability": adjusted_probability,
|
481 |
+
"original_ai_probability": final_ai_probability,
|
482 |
"ps_score": ps_score,
|
483 |
+
"ai_feature_score": ai_feature_score,
|
484 |
"category": category,
|
485 |
"description": description,
|
486 |
"ps_details": ps_details,
|
487 |
+
"ai_details": ai_details,
|
488 |
"individual_model_results": results,
|
489 |
"features": image_features
|
490 |
}
|
491 |
|
492 |
return final_result
|
493 |
|
494 |
+
|
495 |
+
## 8. Gradio界面
|
496 |
+
|
497 |
+
python
|
498 |
# 创建Gradio界面
|
499 |
iface = gr.Interface(
|
500 |
fn=detect_ai_image,
|