图像真伪检测

Poixe AI 图片模型成本对比

模型 单张实际价格(美元) 折合人民币/张(≈7.2汇率) 速度 特点 推荐用途
gemini-3.1-flash-lite $0.000462 ~ $0.000469 ≈0.0033 ~ 0.0034元 ≈1.7秒 成本最低,速度快,适合大量图片分析 批量初筛首选
gpt-4o $0.003250 ~ $0.004182 ≈0.023 ~ 0.030元 ≈6.7秒 图片理解能力强,细节分析稳定 重点图片复核
grok-3 $0.0127968 ~ $0.0162408 ≈0.092 ~ 0.117元 ≈8.6~11秒 推理能力强,但成本最高 疑难图片最终判断
检测数量 gemini-3.1-flash-lite gpt-4o grok-3
1000张 ≈3.3元 ≈25~30元 ≈90~120元
1万张 ≈33元 ≈250~300元 ≈900~1200元
10万张 ≈330元 ≈2500~3000元 ≈9000~12000元
# -*- coding: utf-8 -*-

import sys
import subprocess
import importlib
import os
import base64
import mimetypes
import time
import re
from pathlib import Path


# ==================================================
# 自动安装缺失依赖
# ==================================================

def install_package(package):
    try:
        importlib.import_module(package)
    except ImportError:
        print(f"正在安装依赖: {package}")
        subprocess.check_call([
            sys.executable,
            "-m",
            "pip",
            "install",
            package
        ])


required_packages = [
    "requests",
    "pandas",
    "tqdm",
    "openpyxl"
]

for pkg in required_packages:
    install_package(pkg)


import requests
import pandas as pd
from tqdm import tqdm


# ==================================================
# API 配置
# ==================================================

API_URL = "https://api.poixe.com/v1/chat/completions"

# 不建议把 Key 写死在代码里
# 运行后手动输入更安全
API_KEY = input("请输入你的 Poixe API Key:").strip()

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {API_KEY}"
}


# ==================================================
# 模型选择
# ==================================================

"""
可选模型:

1. gpt-4o
2. grok-3
3. gemini-3.1-flash-lite
"""

MODEL = "gemini-3.1-flash-lite"


# ==================================================
# 图片目录与输出文件
# ==================================================

image_dir = Path(r"C:\img")
output_excel = Path(r"C:\真伪检测结果.xlsx")

INCLUDE_SUBFOLDERS = True


# ==================================================
# 支持格式
# ==================================================

image_ext = {
    ".jpg",
    ".jpeg",
    ".png",
    ".webp",
    ".bmp"
}


# ==================================================
# AI 检测提示词
# ==================================================

prompt = """
你是一名专业的AI生成内容鉴定专家。

请分析上传图片是真实摄影还是AI生成图片。

请从以下方面检查:

1. 人体结构
- 手指数量
- 手部结构
- 四肢比例
- 身体姿态

2. 面部细节
- 五官比例
- 眼睛
- 牙齿
- 耳朵
- 皮肤纹理

3. 光影关系
- 光源方向
- 阴影一致性
- 反射是否符合物理规律

4. 图像物理规律
- 透视
- 景深
- 运动模糊
- 遮挡关系

5. 背景异常
- 文字错误
- 重复纹理
- 边缘融合

6. AI生成特征
- AI水印
- 生成痕迹
- 换脸痕迹

判断:

A 真人实拍

B AI生成、AI修改、换脸、深度伪造

必须选择概率最高结果。

严格输出格式:

最终判断:真实 / AI伪造

置信度:0-100%

最关键三个判断依据:

1.

2.

3.

不要输出其他内容。
"""


# ==================================================
# 图片转 Base64
# ==================================================

def encode_image(path):
    with open(path, "rb") as f:
        return base64.b64encode(f.read()).decode("utf-8")


def get_mime_type(path):
    mime, _ = mimetypes.guess_type(str(path))

    if mime:
        return mime

    suffix = path.suffix.lower()

    if suffix in [".jpg", ".jpeg"]:
        return "image/jpeg"
    elif suffix == ".png":
        return "image/png"
    elif suffix == ".webp":
        return "image/webp"
    elif suffix == ".bmp":
        return "image/bmp"

    return "image/jpeg"


# ==================================================
# 解析模型输出
# ==================================================

def parse_result(text):
    judgment = ""
    confidence = ""
    reason1 = ""
    reason2 = ""
    reason3 = ""

    m = re.search(r"最终判断[::]\s*(真实|AI伪造)", text)
    if m:
        judgment = m.group(1)

    m = re.search(r"置信度[::]\s*([0-9]{1,3}%?)", text)
    if m:
        confidence = m.group(1)
        if not confidence.endswith("%"):
            confidence += "%"

    reasons = re.findall(r"\n\s*[1-3][.、]\s*(.+)", text)

    if len(reasons) > 0:
        reason1 = reasons[0].strip()
    if len(reasons) > 1:
        reason2 = reasons[1].strip()
    if len(reasons) > 2:
        reason3 = reasons[2].strip()

    return judgment, confidence, reason1, reason2, reason3


# ==================================================
# 调用模型
# ==================================================

def analyze_image(path, retry=2):
    img64 = encode_image(path)
    mime_type = get_mime_type(path)

    data = {
        "model": MODEL,
        "messages": [
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": prompt
                    },
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:{mime_type};base64,{img64}"
                        }
                    }
                ]
            }
        ],
        "temperature": 0.2
    }

    last_error = ""

    for attempt in range(retry + 1):
        try:
            response = requests.post(
                API_URL,
                headers=headers,
                json=data,
                timeout=120
            )

            if response.status_code == 200:
                result = response.json()
                return result["choices"][0]["message"]["content"].strip()

            last_error = f"HTTP {response.status_code}: {response.text}"

        except Exception as e:
            last_error = str(e)

        if attempt < retry:
            time.sleep(2)

    return "ERROR: " + last_error


# ==================================================
# 获取图片列表
# ==================================================

def get_image_files(folder):
    if INCLUDE_SUBFOLDERS:
        files = [
            p for p in folder.rglob("*")
            if p.is_file() and p.suffix.lower() in image_ext
        ]
    else:
        files = [
            p for p in folder.iterdir()
            if p.is_file() and p.suffix.lower() in image_ext
        ]

    return sorted(files)


# ==================================================
# 主程序
# ==================================================

def main():
    if not image_dir.exists():
        print(f"图片目录不存在:{image_dir}")
        return

    image_files = get_image_files(image_dir)

    if not image_files:
        print("没有找到支持格式的图片。")
        return

    print(f"共找到 {len(image_files)} 张图片,开始检测...")
    print(f"使用模型:{MODEL}")

    rows = []

    for img_path in tqdm(image_files, desc="检测进度"):
        result_text = analyze_image(img_path)

        if result_text.startswith("ERROR:"):
            judgment = "检测失败"
            confidence = ""
            reason1 = result_text
            reason2 = ""
            reason3 = ""
        else:
            judgment, confidence, reason1, reason2, reason3 = parse_result(result_text)

        rows.append({
            "文件名": img_path.name,
            "完整路径": str(img_path),
            "最终判断": judgment,
            "置信度": confidence,
            "依据1": reason1,
            "依据2": reason2,
            "依据3": reason3,
            "模型原始输出": result_text
        })

    df = pd.DataFrame(rows)

    output_excel.parent.mkdir(parents=True, exist_ok=True)
    df.to_excel(output_excel, index=False)

    print("\n检测完成!")
    print(f"结果已保存到:{output_excel}")


if __name__ == "__main__":
    main()
# -*- coding: utf-8 -*-

import os
import base64
import requests
import pandas as pd
from tqdm import tqdm


# ===============================
# API 配置
# ===============================

url = "https://api.poixe.com/v1/chat/completions"

headers = {
    "Content-Type": "application/json",
    "Authorization": "sk-你的KEY"
}


# ===============================
# 图片目录
# ===============================

image_dir = r"c:\img"

output_excel = r"c:\img\真伪检测结果.xlsx"



# ===============================
# 支持图片格式
# ===============================

image_ext = [
    ".jpg",
    ".jpeg",
    ".png",
    ".webp"
]



# ===============================
# AI检测提示词
# ===============================

prompt = """

你是一名专业的 AI 生成内容鉴定专家。

请对上传的图像进行真实性分析。

结合以下证据判断:

1. 人物肢体细节:

- 手指数量
- 手部结构
- 四肢比例
- 身体姿态
- 是否符合人体运动规律


2. 面部细节:

- 五官比例
- 眼睛
- 牙齿
- 耳朵
- 皮肤纹理
- 表情自然程度


3. 光影与反射:

- 光源方向
- 阴影关系
- 镜面反射
- 环境光一致性


4. 物理规律:

- 透视关系
- 景深
- 运动模糊
- 遮挡关系


5. 背景异常:

- 背景变形
- 文字错误
- 重复纹理
- 边缘融合


6. 图像质量:

- 压缩痕迹
- 局部噪声
- AI生成伪影


7. AI证据:

- 是否存在AI水印
- 是否存在生成标记
- 是否存在换脸痕迹


请判断:

A. 真人实拍或正常摄影图片

B. AI生成、AI换脸、深度伪造、生成式AI修改图片


规则:

- 必须选择 A 或 B。
- 不允许回答无法判断。
- 没有AI水印不能作为真实依据。
- 根据所有证据选择概率最高结果。


严格输出:

最终判断:真实 / AI伪造

置信度:0—100%

最关键的三个判断依据:

1.

2.

3.


不要输出其他内容。

"""



# ===============================
# 图片编码
# ===============================

def encode_image(path):

    with open(path, "rb") as f:

        return base64.b64encode(
            f.read()
        ).decode("utf-8")



# ===============================
# 调用模型
# ===============================

def analyze_image(path):

    img64 = encode_image(path)


    data = {

        "model": "gpt-4o",

        "messages": [

            {

                "role": "user",

                "content": [

                    {
                        "type": "text",
                        "text": prompt
                    },

                    {

                        "type": "image_url",

                        "image_url": {

                            "url":
                            f"data:image/jpeg;base64,{img64}"

                        }

                    }

                ]

            }

        ],

        "temperature":0.2

    }



    response = requests.post(

        url,

        headers=headers,

        json=data,

        timeout=120

    )


    if response.status_code == 200:

        result = response.json()

        return result["choices"][0]["message"]["content"]


    else:

        return "ERROR:" + response.text




# ===============================
# 解析结果
# ===============================

def parse_result(text):


    result = {

        "最终判断":"",
        "置信度":"",
        "依据1":"",
        "依据2":"",
        "依据3":""

    }



    lines = text.split("\n")


    for line in lines:


        line=line.strip()


        if "最终判断" in line:

            result["最终判断"] = (
                line.replace("最终判断:","")
                .replace("最终判断:","")
                .strip()
            )


        elif "置信度" in line:

            result["置信度"] = (
                line.replace("置信度:","")
                .replace("置信度:","")
                .strip()
            )


        elif line.startswith("1."):

            result["依据1"]=line[2:].strip()


        elif line.startswith("2."):

            result["依据2"]=line[2:].strip()


        elif line.startswith("3."):

            result["依据3"]=line[2:].strip()



    return result




# ===============================
# 获取图片列表(包含子文件夹)
# ===============================

files=[]


for root, dirs, filenames in os.walk(image_dir):

    for f in filenames:

        ext=os.path.splitext(f)[1].lower()


        if ext in image_ext:

            full_path=os.path.join(
                root,
                f
            )

            files.append(full_path)



print("====================")
print("发现图片数量:",len(files))
print("====================")




# ===============================
# 批量检测
# ===============================

rows=[]


for path in tqdm(files):


    try:


        ai_result = analyze_image(path)


        parsed = parse_result(
            ai_result
        )


        rows.append({

            "文件名":
            os.path.relpath(
                path,
                image_dir
            ),

            **parsed

        })



    except Exception as e:


        rows.append({

            "文件名":
            os.path.relpath(
                path,
                image_dir
            ),

            "错误":
            str(e)

        })




# ===============================
# 导出Excel
# ===============================


df=pd.DataFrame(rows)


df.to_excel(

    output_excel,

    index=False

)



print("====================")
print("检测完成")
print("输出文件:")
print(output_excel)
print("====================")
❤️ 转载文章请注明出处,谢谢!❤️