以文搜图(Text-to-Image Search)是一种利用文本描述来检索相关图像的技术。基于CLIP(Contrastive Language-Image Pre-training)和Chinese-CLIP模型的以文搜图系统在近年来得到了广泛应用和研究。以下是对这两种模型及其应用的概述。
CLIP模型
CLIP是由OpenAI开发的一种多模态模型,能够将图像和文本映射到同一个潜在向量空间中,从而实现跨模态检索。CLIP模型的核心思想是通过对比学习(contrastive learning)来训练模型,使得相似的图像和文本在向量空间中的距离更近,而不相似的图像和文本距离更远。
CLIP的主要特点
多模态对齐:CLIP能够同时处理图像和文本,将它们映射到同一个向量空间中。
高效检索:通过计算文本和图像向量的相似度,可以快速检索出与文本描述最匹配的图像。
广泛应用:CLIP在图像分类、图像生成、图像检索等多个领域都有应用。
Chinese-CLIP模型
Chinese-CLIP是针对中文数据进行优化的CLIP模型版本。它使用大规模的中文图文对进行训练,能够更好地处理中文文本和图像的匹配任务。
Chinese-CLIP的主要特点
中文优化:专为中文数据设计,能够更准确地理解和处理中文文本。
大规模训练:使用约2亿对中文图文数据进行训练,确保模型在中文环境中的高性能。
多样化应用:适用于中文图文检索、零样本图片分类等任务
构建基于CLIP和Chinese-CLIP的以文搜图系统通常包括以下几个步骤:
数据准备:
收集并清洗图像和对应的文本描述数据。
将图像和文本数据进行预处理,生成嵌入向量。
模型训练:
使用CLIP或Chinese-CLIP模型对图像和文本进行训练,生成图像和文本的嵌入向量。
通过对比学习优化模型,使得相似的图像和文本在向量空间中的距离更近。
索引和检索:
将训练好的图像嵌入向量存储在向量数据库中。
对用户输入的文本查询进行向量化,并计算与数据库中图像嵌入向量的相似度。
返回相似度最高的图像作为检索结果。
from functools import partial
import json
from multiprocessing.pool import ThreadPool as Pool
import gradio as gr
from utils import *
def text2image_gr():
examples = [
["游泳的狗", 20, clip_base, "是"],
["夜晚盛开的荷花", 20, clip_base, "是"],
["一个走在公园里的女孩", 20, clip_base, "是"],
["抱着孩子的男人", 20, clip_base, "是"]
]
title = "<h1 align='center'>中文CLIP文到图搜索应用</h1>"
with gr.Blocks() as demo:
gr.Markdown(title)
gr.Markdown(description)
with gr.Row():
with gr.Column(scale=1):
with gr.Column(scale=2):
text = gr.Textbox(value="戴着眼镜的猫", label="请填写文本", elem_id=0, interactive=True)
num = gr.components.Slider(minimum=0, maximum=50, step=1, value=8, label="返回图片数(可能被过滤部分)", elem_id=2)
model = gr.components.Radio(label="模型选择", choices=[clip_base, clip_large, clip_large_336],
value=clip_base, elem_id=3)
thumbnail = gr.components.Radio(label="是否返回缩略图", choices=[yes, no],
value=yes, elem_id=4)
btn = gr.Button("搜索", )
with gr.Column(scale=100):
out = gr.Gallery(label="检索结果为:").style(grid=4, height=200)
inputs = [text, num, model, thumbnail]
btn.click(fn=clip_api, inputs=inputs, outputs=out)
gr.Examples(examples, inputs=inputs)
return demo
if __name__ == "__main__":
with gr.TabbedInterface(
[text2image_gr()],
["文到图搜索"],
) as demo:
demo.launch(
enable_queue=True,
)
由于Chinese-clip库并没有教程构建自己的数据集,这里为了用Chinese-clip库进行微调,将自己构建的数据进行了对齐,其中
Flickr8K-CN数据集已经给出(数据来源https://github.com/bubbliiiing/clip-pytorch)。
Chinese-clip的图片与文本都有一个id,但是下列给出的数据集并没有id。要用Chinese-clip训练自己构建的数据集,必须满足其库的数据集要求。其中Flickr8K-CN的json文件格式如下,image代表图片的路径,caption代表图片的描述。构建自己的数据库,请使用该库下面的process.ipynb。运行后会生成包含id的图片(base_64格式)、生成包含id的文本。
[
{
"image": "flickr8k-images/2513260012_03d33305cf.jpg",
"caption": [
"A black dog is running after a white dog in the snow .",
"Black dog chasing brown dog through snow",
"Two dogs chase each other across the snowy ground .",
"Two dogs play together in the snow .",
"Two dogs running through a low lying body of water ."
]
},
]
其中利用process.ipynb生成后的文本、图片如下所示。
{"text_id": 1, "text": "在玩滑板的两个女孩。", "image_ids": [1]}
id image
1 img的base64格式
经过上述过程,我们已经包含包含图片与文本的tsv、jsonl文件,如下所示。由于训练的时候Chinese-clip这个库需要利用到lmdb数据库,我们需要把下列文件转成其对应的形式。利用如下脚本。
├── train_imgs.tsv # 图片id & 图片内容
├── train_texts.jsonl # 文本id & 文本内容,连同匹配的图片id列表
├── valid_imgs.tsv
├── valid_texts.jsonl
# DATAPATH代表你创建的文件夹名字,假如你的文件夹叫Flickr8K-CN。其结构可以如下列所示。
Flickr8K-CN
datasets
Flickr8K-CN
├── train_imgs.tsv # 图片id & 图片内容
├── train_texts.jsonl # 文本id & 文本内容,连同匹配的图片id列表
├── valid_imgs.tsv
├── valid_texts.jsonl
lmdb
train
imgs
pair
valid
imgs
pair
# 注意你先需要把Chinese-clip拉取下来,本次Demo是基于Chinese-clip构建的。
python cn_clip/preprocess/build_lmdb_dataset.py \
--data_dir ${DATAPATH}/datasets/${dataset_name}
train,valid
# 把DATAPATH换成自己的
python cn_clip/preprocess/build_lmdb_dataset.py \
--data_dir Flickr8K-CN/datasets/Flickr8K-CN
train,valid
至此,我们已经把自己的数据集构建成Chinese-clip对应的数据格式,还可以进行模型微调。