// ==UserScript== // @name GL人脸五点检测器【极速切帧版|几何全校验】 // @namespace http://tampermonkey.net/ // @version 3.8 // @description 超低延迟极速响应快速切帧;轻量化运算不卡顿;完整全套校验规则 // @match https://ads.aligenie.com/* // @grant none // @run-at document-start // @license MIT // ==/UserScript== (function () { 'use strict'; const frameCache = {}; let currentRecordId = null; let panelDom = null; let contentDom = null; // 验收规定5个固定五官点位 const STANDARD_KP = ["Right Eye","Left Eye","Nose Tip","Right Mouth","Left Mouth"]; let autoCheckTimer = null; // 悬浮面板初始化 function initPanel() { if (panelDom && document.body.contains(panelDom)) return; panelDom = document.createElement('div'); panelDom.style.cssText = ` position: fixed; z-index: 999999999; width: 420px; left:15px; top:70px; background:#fff; border:1px solid #d1d5db; border-radius:10px; box-shadow:0 4px 20px rgba(0,0,0.15); font-family:"Microsoft YaHei"; font-size:13px; overflow:hidden; `; const header = document.createElement('div'); header.style.cssText = `display:flex;gap:6px;align-items:center;padding:8px 12px;background:#f3f4f6;border-bottom:1px solid #ddd;cursor:move`; header.innerHTML = `GL人脸五点‑极速校验`; const btnWrap = document.createElement('div'); btnWrap.style.display = 'flex'; const refreshBtn = makeBtn("↻", ()=>runCheck()); const closeBtn = makeBtn("✕", ()=>panelDom.remove()); btnWrap.append(refreshBtn, closeBtn); header.appendChild(btnWrap); panelDom.append(header); contentDom = document.createElement('div'); contentDom.style.padding = "12px"; contentDom.style.maxHeight = "480px"; contentDom.style.overflowY = "auto"; panelDom.append(contentDom); // 窗口拖拽逻辑 let drag = false, ox, oy; header.onmousedown = e=>{ drag = true; const r = panelDom.getBoundingClientRect(); ox = e.clientX - r.left; oy = e.clientY - r.top; document.onmousemove = ev=>{ panelDom.style.left = (ev.clientX - ox)+'px'; panelDom.style.top = (ev.clientY - oy)+'px'; } document.onmouseup = ()=>{drag=false;document.onmousemove=null} } document.body.appendChild(panelDom); } function makeBtn(text, click){ const s = document.createElement('span'); s.innerText=text; s.style.cssText = `width:26px;height:26px;border-radius:6px;background:#e5e7eb;display:flex;align-items:center;justify-content:center;cursor:pointer;font-weight:bold`; s.onclick = click; return s; } // 极速防抖 60ms 无滞后 function autoRunCheck() { clearTimeout(autoCheckTimer); autoCheckTimer = setTimeout(runCheck, 60); } // 轻量化校验核心 function runCheck(){ initPanel(); if(!currentRecordId || !frameCache[currentRecordId]){ contentDom.innerHTML = `暂无帧缓存,等待加载数据`; return; } const frameData = frameCache[currentRecordId]; let workObj; try{ workObj = JSON.parse(frameData.workResult); }catch{ contentDom.innerHTML = `标注数据解析失败`; return; } // 忽略帧直接跳过运算 if(workObj?.labels?.invalid === "true"){ contentDom.innerHTML = `
ℹ 当前帧为忽略帧,无需校验
`; return; } const items = workObj.items || []; let bboxCount = 0; let faceBox = null; const pointMap = { "Right Eye":[], "Left Eye":[], "Nose Tip":[], "Right Mouth":[], "Left Mouth":[] }; // 单次循环遍历全部标注,减少性能消耗 for(let i=0;i 1) errors.push("❌ 人脸框数量异常,仅允许1个"); // 缺失/重复点位判断 for(const name of STANDARD_KP){ const arr = pointMap[name]; const len = arr.length; if(len === 0) errors.push(`❌ 缺失:${name}`); if(len > 1) errors.push(`❌ ${name}重复${len}个`); } // 五点齐全才执行几何校验,节省算力 const hasAll = pointMap["Right Eye"].length===1 && pointMap["Left Eye"].length===1 && pointMap["Nose Tip"].length===1 && pointMap["Right Mouth"].length===1 && pointMap["Left Mouth"].length===1 && bboxCount===1; if(hasAll){ const [rx,ry] = pointMap["Right Eye"][0]; const [lx,ly] = pointMap["Left Eye"][0]; const [nx,ny] = pointMap["Nose Tip"][0]; const [rmx,rmy] = pointMap["Right Mouth"][0]; const [lmx,lmy] = pointMap["Left Mouth"][0]; const {x1,y1,x2,y2} = faceBox; if(rx >= lx) errors.push("❌ 双眼左右颠倒"); if(Math.abs(ry-ly)>80) errors.push("❌ 双眼高低差过大"); if(!(rx < nx && nx < lx)) errors.push("❌ 鼻尖不在双眼中间"); if(ny <= ry || ny <= ly) errors.push("❌ 鼻尖高于眼睛"); if(rmx >= lmx) errors.push("❌ 嘴角左右颠倒"); if(rmy <= ny || lmy <= ny) errors.push("❌ 嘴角高于鼻尖"); const inBox = (px,py) => px>x1&&pxy1&&py✅ 标注全部合规`; }else{ html = `
⚠ 存在标注异常
`; for(const e of errors){ html += `
${e}
`; } } contentDom.innerHTML = html; } // 仅劫持XHR,移除fetch劫持,消除axios冲突卡顿 const originOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (method,url){ this._url = url; const originSend = this.send; this.send = function(body){ this._body = body; originSend.call(this,body); } this.addEventListener('load',()=>{ if(this.status !== 200) return; try{ const res = JSON.parse(this.responseText); if(this._url.includes("batchFindRecordById") && res.retValue){ for(const frame of res.retValue){ frameCache[frame.recordId] = frame; } autoRunCheck(); } if(this._url.includes("listMarkIssue") && this._body){ const payload = JSON.parse(this._body); currentRecordId = payload.recordId; autoRunCheck(); } }catch{} }) return originOpen.call(this,method,url); } // 高频兜底轮询120ms,极速同步画面 setInterval(autoRunCheck, 120); setTimeout(initPanel,1000); window.runCheck = runCheck; })();