100 lines
4.7 KiB
Python
100 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
||
"""CHAR-004 R3 候选质检 · Qwen-VL · 反乞丐滑坡版标准"""
|
||
import sys, os, json, base64, subprocess
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
from secrets_loader import secret, endpoint
|
||
|
||
API_KEY = secret("SC-004")
|
||
EP = endpoint("EPT-002")
|
||
FALLBACK_EP = "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation"
|
||
|
||
CANDIDATES_DIR = os.path.expanduser("~/guanghulab/video-ai-system/assets/candidates/D157-VA-05-001-R3/CHAR-004-ZhugeFeng")
|
||
CANDIDATES = [f"{CANDIDATES_DIR}/CHAR-004-R3-candidate-{i:02d}-1080x1920.jpg" for i in range(1, 5)]
|
||
|
||
QC_PROMPT = """你是动画资产质量检查员。检查这张CHAR-004诸葛风立绘候选图。规范要求:清贫但整洁、有骨气、不是乞丐不是流民。服装干净,无破洞无补丁无污渍。
|
||
|
||
逐项检查并输出严格JSON:
|
||
|
||
1. 裤子膝盖有没有破洞/破损?(hole_in_pants: true/false)
|
||
2. 衣服下摆有没有毛边/撕裂?(frayed_hem: true/false)
|
||
3. 鞋子干不干净?有泥污没?(dirty_shoes: true/false)
|
||
4. 衣服有没有污渍?(stains: true/false)
|
||
5. 有没有补丁?(patches: true/false)
|
||
6. 整体气质像不像乞丐/流浪汉?(beggar_look: true/false)
|
||
7. 五官清晰无崩坏吗?(face_intact: true/false)
|
||
8. 肢体比例正常吗?(anatomy_ok: true/false)
|
||
9. 画面清晰吗?(clear_image: true/false)
|
||
10. 全身从头到鞋完整吗?(full_body: true/false)
|
||
11. 和苏白CHAR-003的脸像不像?(similar_to_sb: true/false)
|
||
|
||
注意:
|
||
- "磨白"不等于"破洞"——裤子膝盖只有颜色变浅、没有破损开口,hole_in_pants就是false
|
||
- 鞋子没有明显泥污就是dirty_shoes=false
|
||
- 衣领轻微磨毛不等于毛边撕裂——frayed_hem特指明显破损/散开/撕裂
|
||
|
||
输出严格JSON,不要额外文字:
|
||
{"candidate":N,"pass":true/false,"score":0-100,"hole_in_pants":bool,"frayed_hem":bool,"dirty_shoes":bool,"stains":bool,"patches":bool,"beggar_look":bool,"face_intact":bool,"anatomy_ok":bool,"clear_image":bool,"full_body":bool,"similar_to_sb":bool,"summary":"一句话"}"""
|
||
|
||
def encode_image(path):
|
||
with open(path, "rb") as f:
|
||
b64 = base64.b64encode(f.read()).decode()
|
||
ext = path.rsplit(".", 1)[-1].lower()
|
||
mime = {"jpg": "jpeg", "jpeg": "jpeg", "png": "png"}.get(ext, "jpeg")
|
||
return f"data:image/{mime};base64,{b64}"
|
||
|
||
def call_qwen(img):
|
||
body = json.dumps({"model":"qwen-vl-max","input":{"messages":[{"role":"user","content":[{"image":img},{"text":QC_PROMPT}]}]}})
|
||
for ep in [EP, FALLBACK_EP]:
|
||
try:
|
||
proc = subprocess.run(["curl","-s","-m","60","--noproxy","*","-X","POST",ep,"-H",f"Authorization: Bearer {API_KEY}","-H","Content-Type: application/json","--data-binary","@-"],input=body,capture_output=True,text=True,timeout=65)
|
||
if not proc.stdout.strip(): continue
|
||
resp = json.loads(proc.stdout)
|
||
if "output" in resp:
|
||
content = resp["output"]["choices"][0]["message"]["content"][0]["text"]
|
||
if "```" in content:
|
||
content = content.split("```")[1]
|
||
if content.startswith("json"): content = content[4:]
|
||
content = content.split("```")[0]
|
||
return json.loads(content.strip())
|
||
except: continue
|
||
return None
|
||
|
||
def main():
|
||
print("CHAR-004 R3 QC · Qwen-VL")
|
||
results = []
|
||
for i, p in enumerate(CANDIDATES):
|
||
print(f"[{i+1}/4]", end=" ", flush=True)
|
||
qc = call_qwen(encode_image(p))
|
||
if qc:
|
||
s = qc.get("score","?")
|
||
ok = qc.get("pass","?")
|
||
h = qc.get("hole_in_pants","?")
|
||
print(f"score={s} pass={ok} 破洞={h}")
|
||
results.append(qc)
|
||
else:
|
||
print("✗")
|
||
results.append({"candidate":i+1,"pass":False,"error":"api"})
|
||
|
||
ok = sum(1 for r in results if r.get("pass"))
|
||
print(f"\n通过: {ok}/4")
|
||
|
||
for r in results:
|
||
if not r.get("pass"):
|
||
issues = []
|
||
if r.get("hole_in_pants"): issues.append("破洞")
|
||
if r.get("frayed_hem"): issues.append("毛边")
|
||
if r.get("dirty_shoes"): issues.append("脏鞋")
|
||
if r.get("stains"): issues.append("污渍")
|
||
if r.get("beggar_look"): issues.append("乞丐化")
|
||
print(f" 候选{r.get('candidate')} ✗: {', '.join(issues) if issues else '评分不足'} (score={r.get('score')})")
|
||
|
||
report = {"spec":"VA-05-001-R3","asset":"CHAR-004","tool":"qwen-vl-max","results":results,"summary":{"passed":ok,"total":4}}
|
||
with open(os.path.join(CANDIDATES_DIR,"QC-R3-BATCH.json"),"w") as f:
|
||
json.dump(report,f,ensure_ascii=False,indent=2)
|
||
print(f"\n报告: QC-R3-BATCH.json")
|
||
return 0
|
||
|
||
if __name__=="__main__":
|
||
sys.exit(main())
|