Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -39,7 +39,7 @@ for key in models:
|
|
39 |
models[key]["model"] = None
|
40 |
|
41 |
|
42 |
-
##
|
43 |
|
44 |
|
45 |
def process_model_output(model_info, outputs, probabilities):
|
@@ -113,7 +113,7 @@ def process_model_output(model_info, outputs, probabilities):
|
|
113 |
return ai_probability
|
114 |
|
115 |
|
116 |
-
##
|
117 |
|
118 |
|
119 |
def analyze_image_features(image):
|
@@ -144,11 +144,27 @@ def analyze_image_features(image):
|
|
144 |
features["avg_green"],
|
145 |
features["avg_blue"]
|
146 |
]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
# 边缘一致性分析
|
149 |
edges = cv2.Canny(img_cv, 100, 200)
|
150 |
features["edge_density"] = float(np.sum(edges > 0) / (image.width * image.height))
|
151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
# 纹理分析 - 使用灰度共生矩阵
|
153 |
if len(img_array.shape) == 3:
|
154 |
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
|
@@ -164,6 +180,8 @@ def analyze_image_features(image):
|
|
164 |
features["texture_homogeneity"] = float(np.mean(graycoprops(glcm, 'homogeneity')[0]))
|
165 |
features["texture_correlation"] = float(np.mean(graycoprops(glcm, 'correlation')[0]))
|
166 |
features["texture_energy"] = float(np.mean(graycoprops(glcm, 'energy')[0]))
|
|
|
|
|
167 |
|
168 |
# 噪声分析
|
169 |
if len(img_array.shape) == 3:
|
@@ -173,6 +191,12 @@ def analyze_image_features(image):
|
|
173 |
|
174 |
# 噪声分布 - 用于检测噪声是否自然
|
175 |
features["noise_std"] = float(np.std(noise))
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
|
177 |
# 对称性分析 - AI生成图像通常有更高的对称性
|
178 |
if img_cv.shape[1] % 2 == 0: # 确保宽度是偶数
|
@@ -208,11 +232,55 @@ def analyze_image_features(image):
|
|
208 |
high_freq_mean = np.mean(magnitude) - low_freq_mean
|
209 |
|
210 |
features["freq_ratio"] = float(high_freq_mean / max(low_freq_mean, 0.001))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
return features
|
213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
|
215 |
-
##
|
216 |
|
217 |
|
218 |
def check_ai_specific_features(image_features):
|
@@ -220,17 +288,24 @@ def check_ai_specific_features(image_features):
|
|
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.
|
227 |
-
ai_score += 0.
|
228 |
ai_signs.append("图像对称性异常高")
|
|
|
|
|
|
|
229 |
|
230 |
# 检查纹理相关性 - AI生成图像通常纹理相关性高
|
231 |
-
if "texture_correlation" in image_features
|
232 |
-
|
233 |
-
|
|
|
|
|
|
|
|
|
234 |
|
235 |
# 检查边缘与噪声的关系 - AI生成图像通常边缘清晰但噪声不自然
|
236 |
if "edge_density" in image_features and "noise_level" in image_features:
|
@@ -241,25 +316,94 @@ def check_ai_specific_features(image_features):
|
|
241 |
|
242 |
# 检查颜色平滑度 - AI生成图像通常颜色过渡更平滑
|
243 |
if "color_std" in image_features and image_features["color_std"] < 10:
|
244 |
-
ai_score += 0.
|
245 |
ai_signs.append("颜色过渡异常平滑")
|
246 |
|
247 |
# 检查纹理能量 - AI生成图像通常纹理能量分布不自然
|
248 |
-
if "texture_energy" in image_features and image_features["texture_energy"] < 0.
|
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.
|
256 |
ai_signs.append("频率分布不自然")
|
257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
return min(ai_score, 1.0), ai_signs
|
259 |
|
260 |
-
|
261 |
-
|
262 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
263 |
|
264 |
def detect_photoshop_signs(image_features):
|
265 |
"""检测图像中的PS痕迹"""
|
@@ -315,10 +459,10 @@ def detect_photoshop_signs(image_features):
|
|
315 |
return min(ps_score, 1.0), ps_signs
|
316 |
|
317 |
|
318 |
-
##
|
319 |
|
320 |
|
321 |
-
def get_detailed_analysis(ai_probability, ps_score, ps_signs, ai_signs, valid_models_count):
|
322 |
"""提供更详细的分析结果"""
|
323 |
|
324 |
# 根据有效模型数量调整置信度描述
|
@@ -330,34 +474,43 @@ def get_detailed_analysis(ai_probability, ps_score, ps_signs, ai_signs, valid_mo
|
|
330 |
elif valid_models_count == 1:
|
331 |
confidence_prefix = "中等置信度:"
|
332 |
|
333 |
-
#
|
334 |
-
if ai_probability > 0.
|
335 |
category = confidence_prefix + "高概率AI生成"
|
336 |
description = "图像很可能是由AI完全生成,几乎没有真人照片的特征。"
|
337 |
-
elif ai_probability > 0.
|
338 |
-
if
|
|
|
|
|
|
|
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: #
|
345 |
-
if
|
|
|
|
|
|
|
346 |
category = confidence_prefix + "低概率AI生成,高概率PS修图"
|
347 |
description = "图像更可能是真人照片经过大量后期处理,PS痕迹明显。"
|
348 |
else:
|
349 |
category = confidence_prefix + "低概率AI生成"
|
350 |
description = "图像更可能是真人照片,但有一些AI生成或修饰的特征。"
|
351 |
-
else:
|
352 |
-
if
|
|
|
|
|
|
|
353 |
category = confidence_prefix + "真人照片,重度PS修图"
|
354 |
description = "图像基本是真人照片,但经过了大量后期处理,修饰痕迹明显。"
|
355 |
-
elif ps_score > 0.3:
|
356 |
-
category = confidence_prefix + "
|
357 |
-
description = "
|
358 |
-
elif ps_score > 0.1:
|
359 |
-
category = confidence_prefix + "
|
360 |
-
description = "
|
361 |
else:
|
362 |
category = confidence_prefix + "高概率真人照片,几乎无修图"
|
363 |
description = "图像几乎可以确定是未经大量处理的真人照片。"
|
@@ -374,12 +527,16 @@ def get_detailed_analysis(ai_probability, ps_score, ps_signs, ai_signs, valid_mo
|
|
374 |
else:
|
375 |
ai_details = "未检测到明显的AI生成特征。"
|
376 |
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
|
|
|
|
|
|
381 |
|
382 |
|
|
|
383 |
def detect_ai_image(image):
|
384 |
"""主检测函数"""
|
385 |
if image is None:
|
@@ -437,29 +594,42 @@ def detect_ai_image(image):
|
|
437 |
# 分析PS痕迹
|
438 |
ps_score, ps_signs = detect_photoshop_signs(image_features)
|
439 |
|
|
|
|
|
|
|
440 |
# 应用特征权重调整AI概率
|
441 |
adjusted_probability = final_ai_probability
|
442 |
|
443 |
-
# 如果AI
|
444 |
-
if ai_feature_score > 0.
|
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 |
-
#
|
450 |
-
if
|
451 |
-
adjusted_probability
|
452 |
-
|
453 |
-
|
|
|
|
|
|
|
|
|
454 |
|
455 |
# 高纹理相关性通常表示AI生成
|
456 |
-
if "texture_correlation" in image_features and image_features["texture_correlation"] > 0.
|
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 |
|
@@ -471,8 +641,8 @@ def detect_ai_image(image):
|
|
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 |
# 构建最终结果
|
@@ -480,11 +650,13 @@ def detect_ai_image(image):
|
|
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 |
}
|
@@ -492,7 +664,7 @@ def detect_ai_image(image):
|
|
492 |
return final_result
|
493 |
|
494 |
|
495 |
-
##
|
496 |
|
497 |
|
498 |
# 创建Gradio界面
|
@@ -501,10 +673,11 @@ iface = gr.Interface(
|
|
501 |
inputs=gr.Image(type="pil"),
|
502 |
outputs=gr.JSON(),
|
503 |
title="增强型AI图像检测API",
|
504 |
-
description="多模型集成检测图像是否由AI生成,同时分析PS
|
505 |
examples=None,
|
506 |
allow_flagging="never"
|
507 |
)
|
508 |
|
509 |
iface.launch()
|
510 |
|
|
|
|
39 |
models[key]["model"] = None
|
40 |
|
41 |
|
42 |
+
## 第二部分:模型输出处理
|
43 |
|
44 |
|
45 |
def process_model_output(model_info, outputs, probabilities):
|
|
|
113 |
return ai_probability
|
114 |
|
115 |
|
116 |
+
## 第三部分:图像特征分析
|
117 |
|
118 |
|
119 |
def analyze_image_features(image):
|
|
|
144 |
features["avg_green"],
|
145 |
features["avg_blue"]
|
146 |
]))
|
147 |
+
|
148 |
+
# 颜色局部变化 - 真实照片通常有更多局部颜色变化
|
149 |
+
local_color_variations = []
|
150 |
+
for i in range(0, img_array.shape[0]-10, 10):
|
151 |
+
for j in range(0, img_array.shape[1]-10, 10):
|
152 |
+
patch = img_array[i:i+10, j:j+10]
|
153 |
+
local_color_variations.append(np.std(patch))
|
154 |
+
features["local_color_variation"] = float(np.mean(local_color_variations))
|
155 |
|
156 |
# 边缘一致性分析
|
157 |
edges = cv2.Canny(img_cv, 100, 200)
|
158 |
features["edge_density"] = float(np.sum(edges > 0) / (image.width * image.height))
|
159 |
|
160 |
+
# 边缘自然度分析 - 真实照片的边缘通常更自然
|
161 |
+
if len(img_array.shape) == 3:
|
162 |
+
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
|
163 |
+
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
|
164 |
+
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
|
165 |
+
edge_magnitude = np.sqrt(sobelx**2 + sobely**2)
|
166 |
+
features["edge_variance"] = float(np.var(edge_magnitude))
|
167 |
+
|
168 |
# 纹理分析 - 使用灰度共生矩阵
|
169 |
if len(img_array.shape) == 3:
|
170 |
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
|
|
|
180 |
features["texture_homogeneity"] = float(np.mean(graycoprops(glcm, 'homogeneity')[0]))
|
181 |
features["texture_correlation"] = float(np.mean(graycoprops(glcm, 'correlation')[0]))
|
182 |
features["texture_energy"] = float(np.mean(graycoprops(glcm, 'energy')[0]))
|
183 |
+
features["texture_dissimilarity"] = float(np.mean(graycoprops(glcm, 'dissimilarity')[0]))
|
184 |
+
features["texture_ASM"] = float(np.mean(graycoprops(glcm, 'ASM')[0]))
|
185 |
|
186 |
# 噪声分析
|
187 |
if len(img_array.shape) == 3:
|
|
|
191 |
|
192 |
# 噪声分布 - 用于检测噪声是否自然
|
193 |
features["noise_std"] = float(np.std(noise))
|
194 |
+
|
195 |
+
# 噪声频谱分析 - 真实照片的噪声频谱更自然
|
196 |
+
noise_fft = np.fft.fft2(noise[:,:,0])
|
197 |
+
noise_fft_shift = np.fft.fftshift(noise_fft)
|
198 |
+
noise_magnitude = np.abs(noise_fft_shift)
|
199 |
+
features["noise_spectrum_std"] = float(np.std(noise_magnitude))
|
200 |
|
201 |
# 对称性分析 - AI生成图像通常有更高的对称性
|
202 |
if img_cv.shape[1] % 2 == 0: # 确保宽度是偶数
|
|
|
232 |
high_freq_mean = np.mean(magnitude) - low_freq_mean
|
233 |
|
234 |
features["freq_ratio"] = float(high_freq_mean / max(low_freq_mean, 0.001))
|
235 |
+
|
236 |
+
# 频率分布的自然度 - 真实照片通常有更自然的频率分布
|
237 |
+
freq_std = np.std(magnitude)
|
238 |
+
features["freq_std"] = float(freq_std)
|
239 |
+
|
240 |
+
# 尝试检测人脸
|
241 |
+
try:
|
242 |
+
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
|
243 |
+
gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
|
244 |
+
faces = face_cascade.detectMultiScale(gray, 1.1, 4)
|
245 |
+
features["face_count"] = len(faces)
|
246 |
+
|
247 |
+
if len(faces) > 0:
|
248 |
+
# 分析人脸特征
|
249 |
+
face_features = []
|
250 |
+
for (x, y, w, h) in faces:
|
251 |
+
face = img_cv[y:y+h, x:x+w]
|
252 |
+
# 皮肤质感分析
|
253 |
+
face_hsv = cv2.cvtColor(face, cv2.COLOR_BGR2HSV)
|
254 |
+
skin_mask = cv2.inRange(face_hsv, (0, 20, 70), (20, 150, 255))
|
255 |
+
skin_pixels = face[skin_mask > 0]
|
256 |
+
if len(skin_pixels) > 0:
|
257 |
+
face_features.append({
|
258 |
+
"skin_std": float(np.std(skin_pixels)),
|
259 |
+
"skin_local_contrast": float(np.mean(cv2.Laplacian(face, cv2.CV_64F))),
|
260 |
+
"face_symmetry": analyze_face_symmetry(face)
|
261 |
+
})
|
262 |
+
|
263 |
+
if face_features:
|
264 |
+
features["face_skin_std"] = np.mean([f["skin_std"] for f in face_features])
|
265 |
+
features["face_local_contrast"] = np.mean([f["skin_local_contrast"] for f in face_features])
|
266 |
+
features["face_symmetry"] = np.mean([f["face_symmetry"] for f in face_features])
|
267 |
+
except:
|
268 |
+
# 如果人脸检测失败,不添加人脸特征
|
269 |
+
pass
|
270 |
|
271 |
return features
|
272 |
|
273 |
+
def analyze_face_symmetry(face):
|
274 |
+
"""分析人脸对称性"""
|
275 |
+
if face.shape[1] % 2 == 0: # 确保宽度是偶数
|
276 |
+
left_half = face[:, :face.shape[1]//2]
|
277 |
+
right_half = cv2.flip(face[:, face.shape[1]//2:], 1)
|
278 |
+
if left_half.shape == right_half.shape:
|
279 |
+
return 1 - float(np.mean(cv2.absdiff(left_half, right_half)) / 255)
|
280 |
+
return 0.5 # 默认值
|
281 |
+
|
282 |
|
283 |
+
## 第四部分:特征检测函数
|
284 |
|
285 |
|
286 |
def check_ai_specific_features(image_features):
|
|
|
288 |
ai_score = 0
|
289 |
ai_signs = []
|
290 |
|
291 |
+
# 检查对称性 - AI生成图像通常对称性高,但权重降低
|
292 |
if "horizontal_symmetry" in image_features and "vertical_symmetry" in image_features:
|
293 |
avg_symmetry = (image_features["horizontal_symmetry"] + image_features["vertical_symmetry"]) / 2
|
294 |
+
if avg_symmetry > 0.8: # 提高阈值
|
295 |
+
ai_score += 0.2 # 降低权重
|
296 |
ai_signs.append("图像对称性异常高")
|
297 |
+
elif avg_symmetry > 0.7:
|
298 |
+
ai_score += 0.1
|
299 |
+
ai_signs.append("图像对称性较高")
|
300 |
|
301 |
# 检查纹理相关性 - AI生成图像通常纹理相关性高
|
302 |
+
if "texture_correlation" in image_features:
|
303 |
+
if image_features["texture_correlation"] > 0.95: # 提高阈值
|
304 |
+
ai_score += 0.2
|
305 |
+
ai_signs.append("纹理相关性异常高")
|
306 |
+
elif image_features["texture_correlation"] > 0.9:
|
307 |
+
ai_score += 0.1
|
308 |
+
ai_signs.append("纹理相关性较高")
|
309 |
|
310 |
# 检查边缘与噪声的关系 - AI生成图像通常边缘清晰但噪声不自然
|
311 |
if "edge_density" in image_features and "noise_level" in image_features:
|
|
|
316 |
|
317 |
# 检查颜色平滑度 - AI生成图像通常颜色过渡更平滑
|
318 |
if "color_std" in image_features and image_features["color_std"] < 10:
|
319 |
+
ai_score += 0.1 # 降低权重
|
320 |
ai_signs.append("颜色过渡异常平滑")
|
321 |
|
322 |
# 检查纹理能量 - AI生成图像通常纹理能量分布不自然
|
323 |
+
if "texture_energy" in image_features and image_features["texture_energy"] < 0.01:
|
324 |
ai_score += 0.2
|
325 |
ai_signs.append("纹理能量分布不自然")
|
326 |
|
327 |
# 检查频率比例 - AI生成图像通常频率分布不自然
|
328 |
if "freq_ratio" in image_features:
|
329 |
if image_features["freq_ratio"] < 0.1 or image_features["freq_ratio"] > 2.0:
|
330 |
+
ai_score += 0.1 # 降低权重
|
331 |
ai_signs.append("频率分布不自然")
|
332 |
|
333 |
+
# 检查局部颜色变化 - 真实照片通常有更多局部颜色变化
|
334 |
+
if "local_color_variation" in image_features and image_features["local_color_variation"] < 5:
|
335 |
+
ai_score += 0.2
|
336 |
+
ai_signs.append("局部颜色变化异常少")
|
337 |
+
|
338 |
+
# 检查边缘变化 - 真实照片的边缘通常更自然
|
339 |
+
if "edge_variance" in image_features and image_features["edge_variance"] < 100:
|
340 |
+
ai_score += 0.2
|
341 |
+
ai_signs.append("边缘变化异常均匀")
|
342 |
+
|
343 |
+
# 检查噪声频谱 - 真实照片的噪声频谱更自然
|
344 |
+
if "noise_spectrum_std" in image_features and image_features["noise_spectrum_std"] < 1000:
|
345 |
+
ai_score += 0.2
|
346 |
+
ai_signs.append("噪声频谱异常规则")
|
347 |
+
|
348 |
+
# 检查人脸特征 - AI生成的人脸通常有特定特征
|
349 |
+
if "face_symmetry" in image_features and image_features["face_symmetry"] > 0.8:
|
350 |
+
ai_score += 0.2
|
351 |
+
ai_signs.append("人脸对称性异常高")
|
352 |
+
|
353 |
+
if "face_skin_std" in image_features and image_features["face_skin_std"] < 10:
|
354 |
+
ai_score += 0.3
|
355 |
+
ai_signs.append("皮肤质感异常均匀")
|
356 |
+
|
357 |
return min(ai_score, 1.0), ai_signs
|
358 |
|
359 |
+
def detect_beauty_filter_signs(image_features):
|
360 |
+
"""检测美颜滤镜痕迹"""
|
361 |
+
beauty_score = 0
|
362 |
+
beauty_signs = []
|
363 |
+
|
364 |
+
# 检查皮肤质感
|
365 |
+
if "face_skin_std" in image_features:
|
366 |
+
if image_features["face_skin_std"] < 15:
|
367 |
+
beauty_score += 0.3
|
368 |
+
beauty_signs.append("皮肤质感过于均匀,典型美颜特征")
|
369 |
+
elif image_features["face_skin_std"] < 25:
|
370 |
+
beauty_score += 0.2
|
371 |
+
beauty_signs.append("皮肤质感较为均匀,可能使用了美颜")
|
372 |
+
|
373 |
+
# 检查局部对比度 - 美颜通常会降低局部对比度
|
374 |
+
if "face_local_contrast" in image_features:
|
375 |
+
if image_features["face_local_contrast"] < 5:
|
376 |
+
beauty_score += 0.2
|
377 |
+
beauty_signs.append("面部局部对比度低,典型美颜特征")
|
378 |
+
|
379 |
+
# 检查边缘平滑度 - 美颜通常会平滑边缘
|
380 |
+
if "edge_density" in image_features:
|
381 |
+
if image_features["edge_density"] < 0.03:
|
382 |
+
beauty_score += 0.2
|
383 |
+
beauty_signs.append("边缘过于平滑,典型美颜特征")
|
384 |
+
elif image_features["edge_density"] < 0.05:
|
385 |
+
beauty_score += 0.1
|
386 |
+
beauty_signs.append("边缘较为平滑,可能使用了美颜")
|
387 |
+
|
388 |
+
# 检查噪点 - 美颜通常会减少噪点
|
389 |
+
if "noise_level" in image_features:
|
390 |
+
if image_features["noise_level"] < 1.0:
|
391 |
+
beauty_score += 0.2
|
392 |
+
beauty_signs.append("噪点异常少,典型美颜特征")
|
393 |
+
elif image_features["noise_level"] < 2.0:
|
394 |
+
beauty_score += 0.1
|
395 |
+
beauty_signs.append("噪点较少,可能使用了美颜")
|
396 |
+
|
397 |
+
# 检查人脸对称性 - 美颜通常会增加对称性
|
398 |
+
if "face_symmetry" in image_features:
|
399 |
+
if image_features["face_symmetry"] > 0.8:
|
400 |
+
beauty_score += 0.2
|
401 |
+
beauty_signs.append("面部对称性异常高,典型美颜特征")
|
402 |
+
elif image_features["face_symmetry"] > 0.7:
|
403 |
+
beauty_score += 0.1
|
404 |
+
beauty_signs.append("面部对称性较高,可能使用了美颜")
|
405 |
+
|
406 |
+
return min(beauty_score, 1.0), beauty_signs
|
407 |
|
408 |
def detect_photoshop_signs(image_features):
|
409 |
"""检测图像中的PS痕迹"""
|
|
|
459 |
return min(ps_score, 1.0), ps_signs
|
460 |
|
461 |
|
462 |
+
## 第五部分:结果分析与分类
|
463 |
|
464 |
|
465 |
+
def get_detailed_analysis(ai_probability, ps_score, beauty_score, ps_signs, ai_signs, beauty_signs, valid_models_count):
|
466 |
"""提供更详细的分析结果"""
|
467 |
|
468 |
# 根据有效模型数量调整置信度描述
|
|
|
474 |
elif valid_models_count == 1:
|
475 |
confidence_prefix = "中等置信度:"
|
476 |
|
477 |
+
# 调整后的阈值判断,考虑美颜因素
|
478 |
+
if ai_probability > 0.7: # 高AI概率
|
479 |
category = confidence_prefix + "高概率AI生成"
|
480 |
description = "图像很可能是由AI完全生成,几乎没有真人照片的特征。"
|
481 |
+
elif ai_probability > 0.5: # 中等AI概率
|
482 |
+
if beauty_score > 0.6: # 高美颜分数
|
483 |
+
category = confidence_prefix + "可能是重度美颜的真人照片"
|
484 |
+
description = "图像可能是真人照片经过重度美颜处理,也可能是AI生成图像。"
|
485 |
+
elif ps_score > 0.5: # 高PS分数
|
486 |
category = confidence_prefix + "中等概率AI生成,高概率PS修图"
|
487 |
description = "图像可能是真人照片经过大量后期处理,或是AI生成后经过修饰的图像。"
|
488 |
else:
|
489 |
category = confidence_prefix + "中等概率AI生成"
|
490 |
description = "图像有较多AI生成的特征,但也保留了一些真实照片的特点。"
|
491 |
+
elif ai_probability > 0.3: # 低AI概率
|
492 |
+
if beauty_score > 0.5: # 中高美颜分数
|
493 |
+
category = confidence_prefix + "很可能是美颜处理的真人照片"
|
494 |
+
description = "图像很可能是真人照片经过美颜处理,美颜痕迹明显。"
|
495 |
+
elif ps_score > 0.5: # 高PS分数
|
496 |
category = confidence_prefix + "低概率AI生成,高概率PS修图"
|
497 |
description = "图像更可能是真人照片经过大量后期处理,PS痕迹明显。"
|
498 |
else:
|
499 |
category = confidence_prefix + "低概率AI生成"
|
500 |
description = "图像更可能是真人照片,但有一些AI生成或修饰的特征。"
|
501 |
+
else: # 很低AI概率
|
502 |
+
if beauty_score > 0.6:
|
503 |
+
category = confidence_prefix + "真人照片,重度美颜处理"
|
504 |
+
description = "图像基本是真人照片,但经过了重度美颜处理。"
|
505 |
+
elif ps_score > 0.6:
|
506 |
category = confidence_prefix + "真人照片,重度PS修图"
|
507 |
description = "图像基本是真人照片,但经过了大量后期处理,修饰痕迹明显。"
|
508 |
+
elif ps_score > 0.3 or beauty_score > 0.3:
|
509 |
+
category = confidence_prefix + "真人照片,中度修图或美颜"
|
510 |
+
description = "图像是真人照片,有明显的后期处理或美颜痕迹。"
|
511 |
+
elif ps_score > 0.1 or beauty_score > 0.1:
|
512 |
+
category = confidence_prefix + "真人照片,轻度修图或美颜"
|
513 |
+
description = "图像是真人照片,有少量后期处理或美颜。"
|
514 |
else:
|
515 |
category = confidence_prefix + "高概率真人照片,几乎无修图"
|
516 |
description = "图像几乎可以确定是未经大量处理的真人照片。"
|
|
|
527 |
else:
|
528 |
ai_details = "未检测到明显的AI生成特征。"
|
529 |
|
530 |
+
# 添加美颜特征描述
|
531 |
+
if beauty_signs:
|
532 |
+
beauty_details = "检测到的美颜特征:" + "、".join(beauty_signs)
|
533 |
+
else:
|
534 |
+
beauty_details = "未检测到明显的美颜特征。"
|
535 |
+
|
536 |
+
return category, description, ps_details, ai_details, beauty_details
|
537 |
|
538 |
|
539 |
+
## 第六部分:主检测函数
|
540 |
def detect_ai_image(image):
|
541 |
"""主检测函数"""
|
542 |
if image is None:
|
|
|
594 |
# 分析PS痕迹
|
595 |
ps_score, ps_signs = detect_photoshop_signs(image_features)
|
596 |
|
597 |
+
# 分析美颜痕迹
|
598 |
+
beauty_score, beauty_signs = detect_beauty_filter_signs(image_features)
|
599 |
+
|
600 |
# 应用特征权重调整AI概率
|
601 |
adjusted_probability = final_ai_probability
|
602 |
|
603 |
+
# 如果AI特征分数高,提高AI概率
|
604 |
+
if ai_feature_score > 0.7:
|
605 |
adjusted_probability = max(adjusted_probability, 0.7)
|
606 |
+
elif ai_feature_score > 0.5:
|
607 |
+
adjusted_probability = max(adjusted_probability, 0.6)
|
608 |
elif ai_feature_score > 0.3:
|
609 |
adjusted_probability = max(adjusted_probability, 0.5)
|
610 |
|
611 |
+
# 如果美颜分数高但AI特征分数不高,降低AI概率
|
612 |
+
if beauty_score > 0.6 and ai_feature_score < 0.5:
|
613 |
+
adjusted_probability = min(adjusted_probability, 0.5)
|
614 |
+
|
615 |
+
# 高对称性是AI生成的指标,但权重降低
|
616 |
+
if "horizontal_symmetry" in image_features and image_features["horizontal_symmetry"] > 0.8:
|
617 |
+
adjusted_probability += 0.1
|
618 |
+
if "vertical_symmetry" in image_features and image_features["vertical_symmetry"] > 0.8:
|
619 |
+
adjusted_probability += 0.1
|
620 |
|
621 |
# 高纹理相关性通常表示AI生成
|
622 |
+
if "texture_correlation" in image_features and image_features["texture_correlation"] > 0.95:
|
623 |
adjusted_probability += 0.1
|
624 |
|
625 |
# 低边缘密度通常表示AI生成
|
626 |
if image_features["edge_density"] < 0.01:
|
627 |
adjusted_probability += 0.1
|
628 |
|
629 |
+
# 如果检测到人脸特征异常,增加AI概率
|
630 |
+
if "face_skin_std" in image_features and image_features["face_skin_std"] < 10:
|
631 |
+
adjusted_probability += 0.2
|
632 |
+
|
633 |
# 确保概率在0-1范围内
|
634 |
adjusted_probability = min(1.0, max(0.0, adjusted_probability))
|
635 |
|
|
|
641 |
adjusted_probability = (adjusted_probability + ai_detector_prob * 2) / 3
|
642 |
|
643 |
# 获取详细分析
|
644 |
+
category, description, ps_details, ai_details, beauty_details = get_detailed_analysis(
|
645 |
+
adjusted_probability, ps_score, beauty_score, ps_signs, ai_signs, beauty_signs, valid_models
|
646 |
)
|
647 |
|
648 |
# 构建最终结果
|
|
|
650 |
"ai_probability": adjusted_probability,
|
651 |
"original_ai_probability": final_ai_probability,
|
652 |
"ps_score": ps_score,
|
653 |
+
"beauty_score": beauty_score,
|
654 |
"ai_feature_score": ai_feature_score,
|
655 |
"category": category,
|
656 |
"description": description,
|
657 |
"ps_details": ps_details,
|
658 |
"ai_details": ai_details,
|
659 |
+
"beauty_details": beauty_details,
|
660 |
"individual_model_results": results,
|
661 |
"features": image_features
|
662 |
}
|
|
|
664 |
return final_result
|
665 |
|
666 |
|
667 |
+
## 第七部分:Gradio界面
|
668 |
|
669 |
|
670 |
# 创建Gradio界面
|
|
|
673 |
inputs=gr.Image(type="pil"),
|
674 |
outputs=gr.JSON(),
|
675 |
title="增强型AI图像检测API",
|
676 |
+
description="多模型集成检测图像是否由AI生成,同时分析PS修图和美颜痕迹",
|
677 |
examples=None,
|
678 |
allow_flagging="never"
|
679 |
)
|
680 |
|
681 |
iface.launch()
|
682 |
|
683 |
+
|