用 JavaScript 和 TensorFlow.js 实现图像验证码识别
本教程介绍如何使用前端技术(JavaScript + TensorFlow.js)实现一个简单的图像验证码识别系统,适用于浏览器或 Node.js 环境。
- 准备环境
确保你安装了 Node.js 和相关依赖。 
npm install @tensorflow/tfjs-node canvas
2. 准备训练数据
你可以使用 Python 脚本生成图像验证码数据(与之前相同):
from captcha.image import ImageCaptcha
import random, string, os
更多内容访问ttocr.com或联系1436423940
characters = string.digits + string.ascii_uppercase
generator = ImageCaptcha(width=160, height=60)
os.makedirs("js_captcha", exist_ok=True)
for i in range(5000):
text = ''.join(random.choices(characters, k=4))
image = generator.generate_image(text)
image.save(f"js_captcha/{text}_{i}.png")
3. 加载图片与标签
const fs = require('fs');
const tf = require('@tensorflow/tfjs-node');
const { createCanvas, loadImage } = require('canvas');
const characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const charToIndex = Object.fromEntries(characters.split('').map((c, i) => [c, i]));
async function loadCaptcha(filePath) {
const image = await loadImage(filePath);
const canvas = createCanvas(160, 60);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, 160, 60);
const data = ctx.getImageData(0, 0, 160, 60).data;
const input = [];
for (let i = 0; i < data.length; i += 4) {
input.push(data[i] / 255); // 使用 R 通道
}
const label = filePath.split('/').pop().split('_')[0].split('').map(c => charToIndex[c]);
return { input, label };
}
4. 构建模型结构
function buildModel() {
const model = tf.sequential();
model.add(tf.layers.dense({ inputShape: [160 * 60], units: 512, activation: 'relu' }));
model.add(tf.layers.dropout({ rate: 0.3 }));
model.add(tf.layers.dense({ units: 4 * characters.length, activation: 'softmax' }));
model.compile({
optimizer: tf.train.adam(0.001),
loss: 'categoricalCrossentropy',
metrics: ['accuracy']
});
return model;
}
注意:输出层大小为 36 × 4 = 144,将每个字符的位置展开。
- 训练模型
 
async function trainModel(model, inputs, labels) {
const xs = tf.tensor2d(inputs);
const ys = tf.tensor2d(labels);
await model.fit(xs, ys, {
batchSize: 64,
epochs: 10,
callbacks: tf.callbacks.earlyStopping({ monitor: 'loss', patience: 2 })
});
}
你需要将标签转为 one-hot 编码格式:
function oneHotLabel(label) {
const result = new Array(characters.length * 4).fill(0);
label.forEach((charIdx, i) => {
result[i * characters.length + charIdx] = 1;
});
return result;
}
6. 预测验证码
async function predict(model, filePath) {
const { input } = await loadCaptcha(filePath);
const prediction = model.predict(tf.tensor2d([input]));
const values = prediction.dataSync();
const result = [];
for (let i = 0; i < 4; i++) {
const slice = values.slice(i * characters.length, (i + 1) * characters.length);
const index = slice.indexOf(Math.max(...slice));
result.push(characters[index]);
}
console.log('Predicted:', result.join(''));
}
                    
                
                
            
        
浙公网安备 33010602011771号