本帖最后由 hygzs 于 2025-1-3 15:26 编辑
目标
使用纯代码进行识别AI生成图
网址
aHR0cHM6Ly9hY2NvdW50cy5xcS5jb20vbG9naW4vbGltaXQ=
原因
最近企鹅号大批量封号,还有误封,导致账号封禁,所以想写个自动查是否封号和封号多久的,但是由于他是AI生成图片,进行点选,所以另辟赛道实现一下算出点选,不借助模型去识别
先说思路
刷新了多张图片可以发现,他会生成6张图片,其中有2张图片孤立于其他4张,并且这2张相似,所以,我只需要对比所有图片的相似度,然后找出图片相似,但是孤立的,就很大可能是我所需要的,然后我任选其一点击即可
准备工作
[HTML] 纯文本查看 复制代码 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>喵呜</title>
<script src="https://captcha.gtimg.com/TCaptcha.js"></script>
<script type="text/javascript">
window.TCaptchaId = "2028665724";
window.TCaptchaApiDomain = "https://t.captcha.qq.com";
window.TCaptchaTaskId =
new URLSearchParams(location.search).get("id") || "";
window.TCaptchaCallback = async function (t = {}) {
console.log(t);
};
</script>
</head>
<body>
<script>
const id = window.TCaptchaTaskId;
if (!id) {
document.body.style.margin = "20px";
document.body.innerHTML = "<h1>?</h1>";
} else {
new window.TencentCaptcha(window.TCaptchaId, window.TCaptchaCallback, {
type: "full",
showHeader: false,
enableAged: true,
enableDarkMode: "force",
}).show();
}
</script>
</body>
</html>
搭建一个html,不去他的网页,防止出现不好的影响
这里选择node作为开发语言,为了节省时间,就不去分析他的图片来源的完整流程使用puppeteer来进行获取图片这一步骤
尝试使用puppeteer直接打开,发现网页有检测所以
[JavaScript] 纯文本查看 复制代码 const puppeteer = require("puppeteer-extra");
const pluginStealth = require("puppeteer-extra-plugin-stealth");
puppeteer.use(pluginStealth());
使用puppeteer-extra 绕过检测
接下来编写代码
[JavaScript] 纯文本查看 复制代码 (async () => {
const browser = await puppeteer.launch({
// headless: "new",
headless: false,
args: ["--disable-site-isolation-trials"]
});
//创建一个浏览器,headless: false,展示出来
const page = await browser.newPage();
page.on('response', async (response) => {
const responseUrl = response.url();
if (responseUrl.includes("t.captcha.qq.com/cap_union_new_getcapbysig?img")) {
const picBuf = await response.buffer();
//这里拿到图片
}
});
await page.goto("", { waitUntil: "networkidle0" });
//这里图片地址
await page.waitForSelector("#tcaptcha_iframe_dy");
const frame = await page.frames()[1];
await frame.waitForSelector("#slideBg");
const slideBg = await frame.evaluate(() => {
const img = document.querySelector("#slideBg");
const rect = img.getBoundingClientRect();
const width = rect.width / 3;
const height = rect.height / 2;
const centers = [];
for (let i = 0; i < 2; i++) {
for (let j = 0; j < 3; j++) {
const x = rect.left + width * (j + 0.5);
const y = rect.top + height * (i + 0.5);
centers.push({ x, y });
}
}
return centers;
});
//把图片分割6份返回坐标的位置
})();
开始研究
图片相似算法有很多,例如 感知哈希(pHash)、结构相似性指数(SSIM)、余弦相似度等,我这里为了测试一下可能性,简单写一个通过色系判断,试试可能性
[JavaScript] 纯文本查看 复制代码
async function extractImageParts(imagePath) {
const verifyImg = sharp(imagePath).extract({
left: 0,
top: 34,
width: 672,
height: 480 - 34,
});
const verifyList = [];
let index = 1;
for (let i = 0; i < 2; i++) {
for (let j = 0; j < 3; j++) {
const left = j * 226;
const top = i * 226;
const task = verifyImg.extract({
left: left,
top: top,
width: 220,
height: 220,
});
const buf = await task.toBuffer();
fs.writeFileSync(`d:\\验证码\\${index}.jpg`, buf);
verifyList.push(buf);
index++;
}
}
return verifyList;
}
async function calculateAverageColors(verifyList) {
return await Promise.all(
verifyList.map(getAverageColor)
);
}
async function getAverageColor(buffer) {
const { data, info } = await sharp(buffer)
.resize({ width: 12, height: 12 })
.raw()
.toBuffer({ resolveWithObject: true });
let totalR = 0, totalG = 0, totalB = 0;
for (let i = 0; i < data.length; i += 3) {
totalR += data[i];
totalG += data[i + 1];
totalB += data[i + 2];
}
const numPixels = info.width * info.height;
return [
Math.round(totalR / numPixels),
Math.round(totalG / numPixels),
Math.round(totalB / numPixels),
];
}
使用sharp进行对图片分割,分割成3*2的220*220的图片,然后缩小图片,获得缩略图
[JavaScript] 纯文本查看 复制代码 function calculateColorDistance(color1, color2) {
const [r1, g1, b1] = color1;
const [r2, g2, b2] = color2;
return Math.sqrt(
Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2)
);
}
function generateSimilarityMatrix(averageColors) {
const similarityMatrix = [];
for (let i = 0; i < averageColors.length; i++) {
const row = [];
for (let j = 0; j < averageColors.length; j++) {
if (i === j) {
row.push(1);
} else {
const distance = calculateColorDistance(averageColors[i], averageColors[j]);
row.push(1 - distance / 441.67);
}
}
similarityMatrix.push(row);
}
return similarityMatrix;
}
初始化:创建一个空的相似度矩阵 similarityMatrix。
双重循环:遍历 averageColors 数组,构建矩阵的每一行和每一列。
对角线处理:当 i === j 时,将对角线元素设为1。
计算相似度:对于非对角线元素,调用 calculateColorDistance 函数计算颜色距离,并根据公式 1 - distance / 441.67 计算相似度。
返回结果:最终返回生成的相似度矩阵。
(index) |
0 |
1 |
2 |
3 |
4 |
5 |
0 |
1 |
0.9197588917215598 |
0.8420127694937893 |
0.7422663723537234 |
0.6638008992328004 |
0.7710088553130863 |
1 |
0.9197588917215598 |
1 |
0.9214048726075587 |
0.8207755344292046 |
0.7423558925559035 |
0.8489804048665086 |
2 |
0.8420127694937893 |
0.9214048726075587 |
1 |
0.8928177111549833 |
0.8190108552384238 |
0.9242952725007336 |
3 |
0.7422663723537234 |
0.8207755344292046 |
0.8928177111549833 |
1 |
0.915132724368912 |
0.9568624563967268 |
4 |
0.6638008992328004 |
0.7423558925559035 |
0.8190108552384238 |
0.915132724368912 |
1 |
0.8926027013323846 |
5 |
0.7710088553130863 |
0.8489804048665086 |
0.9242952725007336 |
0.9568624563967268 |
0.8926027013323846 |
1 |
经过测试,只使用色系来进行识别的成功率有50以上,如果优化相似度算法,应该能达到80以上
上个gif图
|