使用 Java 和 DJL 实现图像验证码识别

验证码识别作为图像分类的一种特殊形式,可以通过深度学习模型实现自动解码。虽然大多数教程使用 Python 编写,但本文将展示如何使用 Java 和 ​​DJL(Deep Java Library)​​ 实现一个完整的验证码识别系统。

  1. 准备工作
    确保你的开发环境满足以下条件:
    • JDK 8 以上
    • Maven 3.x
    • 已安装 Python,用于生成训练数据和训练模型(建议使用 PyTorch)
    添加 Maven 依赖


    ai.djl
    api
    0.25.0
    更多内容访问ttocr.com或联系1436423940


    ai.djl.pytorch
    pytorch-engine
    0.25.0


    ai.djl.pytorch
    pytorch-model-zoo
    0.25.0

    2. 模型准备(Python)
    训练部分推荐使用 PyTorch,然后保存为 TorchScript 格式:

train_and_export.py

import torch
import torch.nn as nn
import torchvision.transforms as transforms
from captcha.image import ImageCaptcha
import string
import random
from PIL import Image

模型定义略(CNN + LSTM)

假设你已经训练好一个模型

保存为 TorchScript

example_input = torch.randn(1, 3, 60, 160)
traced = torch.jit.trace(model, example_input)
traced.save("captcha_model.pt")3. 加载模型并预测(Java)
import ai.djl.Model;
import ai.djl.inference.Predictor;
import ai.djl.modality.cv.ImageFactory;
import ai.djl.modality.cv.transform.;
import ai.djl.ndarray.
;
import ai.djl.ndarray.types.Shape;
import ai.djl.translate.*;
import ai.djl.translate.TranslateException;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.*;

public class CaptchaRecognizer {

private static final String[] CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

public static void main(String[] args) throws IOException, TranslateException {
    // 加载模型
    Model model = Model.newInstance("captcha");
    model.load(Paths.get("models")); // 模型路径

    // 加载图片
    var image = ImageFactory.getInstance().fromFile(Paths.get("captcha_samples/B8ZK_0.png"));

    // 构建 Translator
    Translator<ai.djl.modality.cv.Image, String> translator = new Translator<>() {
        @Override
        public NDList processInput(TranslatorContext ctx, ai.djl.modality.cv.Image input) {
            NDArray array = input.toNDArray(ctx.getNDManager());
            array = array.transpose(2, 0, 1).div(255f);
            array = array.expandDims(0); // [1, 3, H, W]
            return new NDList(array);
        }

        @Override
        public String processOutput(TranslatorContext ctx, NDList list) {
            NDArray output = list.get(0); // [1, 4, 36]
            int[] shape = output.getShape().getShape();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < shape[1]; i++) {
                NDArray charLogits = output.get(0).get(i); // 第i位字符的预测
                int index = charLogits.argMax().getInt();
                sb.append(CHARS[index]);
            }
            return sb.toString();
        }

        @Override
        public Batchifier getBatchifier() {
            return null;
        }
    };

    // 创建预测器
    try (Predictor<ai.djl.modality.cv.Image, String> predictor = model.newPredictor(translator)) {
        String result = predictor.predict(image);
        System.out.println("识别结果: " + result);
    }
}

}

posted @ 2025-05-03 13:54  ttocr、com  阅读(99)  评论(0)    收藏  举报