【验证码识别专栏】大炮打麻雀 — CLIP 图文多模态模型,人均通杀 AIGC 六、九宫格验证码!
字数 1512 2025-08-20 18:17:59
CLIP多模态模型在验证码识别中的应用教学文档
一、CLIP模型概述
1.1 CLIP简介
CLIP(Contrastive Language-Image Pre-Training)是由OpenAI在2021年发布的多模态预训练神经网络模型,统一了图像和自然语言的表示空间。
1.2 核心特点
- 对比学习:通过图像-文本对训练,使匹配的特征接近,不匹配的特征远离
- 大规模预训练:使用超过4亿对互联网图像-文本数据
- 零样本学习:无需微调即可处理未见过的任务
- 多任务能力:包括OCR、地理定位、动作识别等
1.3 模型架构
- 视觉编码器:ResNet或ViT架构
- 文本编码器:Transformer架构
二、Chinese-CLIP介绍
2.1 汉化版本
Chinese-CLIP是CLIP的汉化版本,使用中文版RoBERTa文本编码器,支持中文文本处理。
2.2 可用模型
| 模型规模 | 视觉骨架 | 参数量 | 文本骨架 | 文本参数量 | 分辨率 |
|---|---|---|---|---|---|
| CN-CLIPRN50 | ResNet50 | 77M | RBT3 | 39M | 224 |
| CN-CLIPViT-B/16 | ViT-B/16 | 188M | RoBERTa-wwm-Base | 102M | 224 |
| CN-CLIPViT-L/14 | ViT-L/14 | 406M | RoBERTa-wwm-Base | 102M | 224 |
| CN-CLIPViT-L/14@336px | ViT-L/14 | 407M | RoBERTa-wwm-Base | 102M | 336 |
| CN-CLIPViT-H/14 | ViT-H/14 | 958M | RoBERTa-wwm-Large | 326M | 224 |
三、环境准备
3.1 本地环境要求
- Python >= 3.6.4
- PyTorch >= 1.8.0 (with torchvision >= 0.9.0)
- CUDA Version >= 10.2
3.2 AutoDL推荐环境
- 镜像:PyTorch 2.0.0 Python 3.8(ubuntu20.04) Cuda 11.8
- 内存:80GB
- 硬盘:系统盘30GB + 数据盘50GB(建议扩容)
四、数据集准备
4.1 数据集结构
${DATAPATH}
datasets/
KG_GE/
train_imgs.tsv
train_texts.jsonl
valid_imgs.tsv
valid_texts.jsonl
test_imgs.tsv
test_texts.jsonl
4.2 数据格式转换
- 图片转换:将图片转换为base64格式存入TSV文件
- 文本信息:JSONL格式存储文本及匹配关系
- 数据集分割:推荐比例0.9:0.1:0.1
4.3 转换代码示例
import os
import random
import base64
from PIL import Image
from io import BytesIO
from sklearn.model_selection import train_test_split
def image_to_base64(file_path):
with Image.open(file_path) as img:
img_buffer = BytesIO()
img.save(img_buffer, format=img.format)
return base64.b64encode(img_buffer.getvalue()).decode('utf-8')
def save_images_to_split_tsv(image_dir, output_dir, ratios=(0.8,0.1,0.1)):
image_files = os.listdir(image_dir)
train, test = train_test_split(image_files, test_size=ratios[2])
train, val = train_test_split(train, test_size=ratios[1]/(ratios[0]+ratios[1]))
for split, files in zip(['train','val','test'], [train,val,test]):
with open(f"{output_dir}/{split}_imgs.tsv", 'w') as f:
for file in files:
f.write(f"{random.randint(1e14,1e15-1)}\t{image_to_base64(os.path.join(image_dir,file))}\n")
4.4 转换为LMDB格式
python cn_clip/preprocess/build_lmdb_dataset.py \
--data_dir ${DATAPATH}/datasets/KG_GE \
--splits train,valid,test
五、模型训练
5.1 训练脚本关键参数
GPUS_PER_NODE=1
WORKER_CNT=1
export MASTER_ADDR=localhost
export MASTER_PORT=8514
export RANK=0
train_data=${DATAPATH}/datasets/KG_GE/lmdb/train
val_data=${DATAPATH}/datasets/KG_GE/lmdb/valid
resume=${DATAPATH}/pretrained_weights/clip_cn_rn50.pt
context_length=52
warmup=100
batch_size=128
valid_batch_size=20
lr=5e-5
wd=0.001
max_epochs=150
vision_model=RN50
text_model=RBT3-chinese
5.2 启动训练
bash run_scripts/tx_rs50_rbt-base.sh /path/to/TX_6icon
六、模型转换与部署
6.1 ONNX转换准备
pip install torch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1
pip install onnx onnxruntime-gpu onnxmltools
6.2 转换脚本
python cn_clip/deploy/pytorch_to_onnx.py \
--model-arch RN50 \
--pytorch-ckpt-path /root/epoch_latest.pt \
--save-onnx-path /root/autodl-tmp/TX_6icon/deploy/tx666 \
--convert-text --convert-vision
6.3 推理部署代码
import onnxruntime
from PIL import Image
import numpy as np
import torch
import cn_clip.clip as clip
from clip import load_from_name, available_models
from clip.utils import _MODELS, _MODEL_INFO
# 初始化ONNX模型
img_sess = onnxruntime.InferenceSession('tx666.img.fp16.onnx',
providers=["CUDAExecutionProvider"])
txt_sess = onnxruntime.InferenceSession('tx666.txt.fp16.onnx',
providers=["CUDAExecutionProvider"])
# 预处理
preprocess = image_transform(_MODEL_INFO['RN50']['input_resolution'])
def calculate_matching_probability(text: str, image: Image.Image) -> float:
# 图像预处理
img = preprocess(image)
if isinstance(img, np.ndarray):
img = np.expand_dims(img.astype(np.float32), axis=0)
elif isinstance(img, torch.Tensor):
img = img.float().unsqueeze(0).cpu().numpy()
# 提取特征
img_feat = img_sess.run(["unnorm_image_features"], {"image": img})[0]
img_feat /= np.linalg.norm(img_feat, axis=-1, keepdims=True)
# 文本处理
text_tokens = clip.tokenize(["参考文本", text], context_length=52)
text_feats = []
for token in text_tokens:
feat = txt_sess.run(["unnorm_text_features"],
{"text": np.expand_dims(token, axis=0)})[0]
text_feats.append(feat)
text_feats = np.vstack(text_feats)
text_feats /= np.linalg.norm(text_feats, axis=1, keepdims=True)
# 计算相似度
logits = 100 * np.dot(img_feat, text_feats.T)
probs = np.exp(logits - np.max(logits)) / \
np.sum(np.exp(logits - np.max(logits)), axis=-1, keepdims=True)
return probs[0][1]
七、注意事项
- 训练环境:训练与ONNX转换所需的PyTorch版本不同,需分别配置
- 保存频率:调整save-step-frequency避免存储空间不足
- 数据盘选择:训练时务必使用数据盘而非系统盘
- 推理适配:注意处理不同环境下的图像输入格式差异
- 性能优化:GPU环境下6图识别可达毫秒级响应
八、扩展应用
- 截图识别:结合图像分割技术处理截图验证码
- 多模态搜索:扩展至图文检索等应用场景
- 生成模型辅助:用于指导图像生成过程
通过本方案,可利用CLIP强大的多模态理解能力高效解决验证码识别问题,同时该框架也可灵活适配其他类似任务。