深度学习实践:使用 YOLOv3-Tiny 进行验证码识别(Java 实现)

在深度学习领域,YOLO(You Only Look Once)模型因其速度和准确率在目标检测任务中备受瞩目。YOLOv3-Tiny 版本尤其适用于需要快速检测的应用场景。在这篇文章中,我们将使用 Java 实现基于 YOLOv3-Tiny 的验证码识别任务。

准备工作
系统与环境
操作系统:Ubuntu 16.04
Java 版本:8+
CUDA 版本:10.0
GPU:GeForce GTX 1080
工具与资源
Darknet:深度学习框架,用于实现 YOLO 模型 GitHub - Darknet
labelImg:用于标注训练数据的工具 GitHub - labelImg
Deep Java Library (DJL):用于在 Java 中使用深度学习模型的开源库 GitHub - DJL
实践步骤
安装环境
首先,确保 CUDA 等环境已安装完毕。我们将使用 GPU 进行训练。然后,将 Darknet 克隆到本地:

bash

git clone https://github.com/pjreddie/darknet
cd darknet
编译 Darknet
进入 darknet 文件夹,修改 Makefile 文件:

Makefile

GPU=1  # 使用 GPU
CUDNN=1  # 使用 CUDNN
OPENCV=0  # 不使用 OpenCV
OPENMP=0
DEBUG=0
使用以下命令进行编译:

bash

make
编译完成后,会生成一个名为 darknet 的二进制文件。

修改配置文件
我们选择 cfg/yolov3-tiny.cfg 文件进行修改,以适应我们的任务需求:

ini

# Line 3
batch=24  # 每个训练步骤使用 24 张图片

# Line 4
subdivisions=8  # 将 batch 分成 8 个部分

# Line 127
filters=(classes + 5)*3  # 我们的任务中 filters=18

# Line 135
classes=1  # 我们要检测的类别数

# Line 171
filters=(classes + 5)*3  # 同上

# Line 177
classes=1  # 同上
关于 filters = (classes + 5) * 3 的计算方式,可以参考 YOLOv3 论文第 2.3 节内容 YOLOv3 Paper。

准备数据
我们使用 Selenium 的 Google Driver 下载了大量验证码图片,然后使用 labelImg 工具进行数据标注。

下载并编译 labelImg:

bash

git clone https://github.com/tzutalin/labelImg
cd labelImg
pip install pyqt5 lxml
make qt5py3
完成安装后,使用 labelImg 工具进行图片的标注工作。由于我们只有一类内容,因此标注的框只有一类。

生成训练数据
将标注好的数据整理成训练所需的格式。我们编写了 data.py 脚本生成训练数据配置文件,并将标注文件转换为 darknet 可识别的格式。

python

import os
import glob

def generate_txt_file(img_dir, output_file):
    img_files = glob.glob(os.path.join(img_dir, '*.jpg'))
    with open(output_file, 'w') as f:
        for img in img_files:
            f.write(img + '\n')

# 使用示例
generate_txt_file('imgs', 'train.txt')
generate_txt_file('imgs_val', 'val.txt')
下载预训练权重
在 weights 文件夹下使用 darknet53.sh 文件下载预训练的权重文件:

bash

cd weights
./darknet53.sh
配置文件准备
在 data 文件夹中准备如下文件:

train.txt - 训练数据文件,由 data.py 生成
char.names - 类别配置文件
val.txt - 验证数据文件
train.data - 训练配置表
开始训练
进入 darknet 文件夹,使用以下命令开始训练:

bash

./darknet detector train data/train.data cfg/yolov3-tiny.cfg weights/darknet53.conv.74 -gpus 0
通常,当训练的 loss 达到 0.6 左右时,就可以停止训练。

验证结果
使用以下命令验证训练好的模型:

bash

./darknet detector test data/train.data cfg/yolov3-tiny.cfg weights/yolov3-tiny_final.weights test_imgs/1.jpg -thresh 0.5 -gpus 0
在 darknet 文件夹中会生成一个名为 predictions.jpg 的文件,这是我们验证出来的结果文件。

Java 代码实现
我们使用 Java 语言来实现上述过程中的部分关键步骤。以下是 Java 代码示例:

安装依赖库
首先,我们需要安装必要的 Java 库。我们将使用 DJL 库来进行图像处理和目标检测。

在 pom.xml 中添加以下依赖:

xml

<dependency>
    <groupId>ai.djl.tensorflow</groupId>
    <artifactId>tensorflow-engine</artifactId>
    <version>0.14.0</version>
</dependency>
<dependency>
    <groupId>ai.djl.tensorflow</groupId>
    <artifactId>tensorflow-model-zoo</artifactId>
    <version>0.14.0</version>
</dependency>
<dependency>
    <groupId>ai.djl.tensorflow</groupId>
    <artifactId>tensorflow-model</artifactId>
    <version>0.14.0</version>
</dependency>
<dependency>
    <groupId>ai.djl.tensorflow</groupId>
    <artifactId>tensorflow-native-auto</artifactId>
    <version>2.7.0</version>
</dependency>
<dependency>更多内容联系1436423940
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.32</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.32</version>
</dependency>
读取配置文件并进行推理
我们将使用 DJL 库来进行图像处理和目标检测。

java

import ai.djl.Application;
import ai.djl.Model;
import ai.djl.ModelException;
import ai.djl.ModelZoo;
import ai.djl.basicdataset.cv.classification.ImageFolder;
import ai.djl.basicdataset.cv.classification.ImageNet;
import ai.djl.basicmodelzoo.BasicModelZoo;
import ai.djl.inference.Predictor;
import ai.djl.modality.Classifications;
import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
import ai.djl.modality.cv.transform.Resize;
import ai.djl.ndarray.NDArray;
import ai.djl.ndarray.NDManager;
import ai.djl.ndarray.types.Shape;
import ai.djl.repository.zoo.Criteria;
import ai.djl.repository.zoo.ModelZoo;
import ai.djl.repository.zoo.ZooModel;
import ai.djl.training.util.ProgressBar;
import ai.djl.translate.TranslateException;
import ai.djl.translate.Translator;
import ai.djl.translate.TranslatorContext;
import ai.djl.translate.TranslatorFactory;
import ai.djl.util.Utils;
import ai.djl.util.Pair;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class YOLODetection {

    public static void main(String[] args) throws IOException, ModelException, TranslateException {
        String modelDir = "path/to/yolov3-tiny";
        String imageFilePath = "test_imgs/1.jpg";
        String outputImagePath = "predictions.jpg";

        Criteria<Image, Classifications> criteria = Criteria.builder()
                .setTypes(Image.class, Classifications.class)
                .optModelPath(Paths.get(modelDir))
                .optTranslator(new YoloTranslator())
                .optEngine("TensorFlow")
                .build();

        try (ZooModel<Image, Classifications> model = ModelZoo.loadModel(criteria);
             Predictor<Image, Classifications> predictor = model.newPredictor()) {

            Image img = ImageFactory.getInstance().fromFile(Paths.get(imageFilePath));
            Classifications classifications = predictor.predict(img);
            saveBoundingBoxImage(classifications, img, outputImagePath);
        }
    }

    private static void saveBoundingBoxImage(Classifications classifications, Image img, String outputImagePath) throws IOException {
        BufferedImage bufferedImage = (BufferedImage) img.getWrappedImage();
        // Draw bounding boxes on bufferedImage using classifications
        // Save bufferedImage to outputImagePath
    }
}

class YoloTranslator implements Translator<Image, Classifications> {

    @Override
    public NDArray processInput(TranslatorContext ctx, Image input) {
        return input.toNDArray(ctx.getNDManager()).div(255.0f).expandDims(0);
    }

    @Override
    public Classifications processOutput(TranslatorContext ctx, NDArray list) {
        // Parse NDArray output to Classifications
    }

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

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值