图片搜索快速入门
本文通过一个完整示例,介绍如何使用 AnalyticDB for MySQL 图片搜索 API,搭建一个同时支持以文搜图和以图搜图的图像检索系统。示例使用公开图片数据,您可以跟随操作快速体验图片入库和语义检索的完整流程。
背景信息
AnalyticDB for MySQL 图片搜索服务基于多模态大模型和向量检索技术,提供图片库管理、图片导入和图片检索 API。您可以通过图片库统一管理图片数据,通过 OSS JSONL 文件批量入库,并在应用中调用以文搜图或以图搜图接口完成相似图片召回。
图片库支持以下三种工作模式:
模式 | 适用场景 | 检索能力 | 说明 |
| 商品、服饰等特定物品检索 | 以图搜图 | 创建时需指定关注物品名称。 |
| 企业图库、内容推荐、多类别自然图片 | 以图搜图、以文搜图 | 面向整图语义检索,适合本文使用的公开自然图片。 |
| 人脸与普通图片混合检索 | 以图搜图 | 根据图片属性在人脸检索和整图语义检索之间自适应处理。 |
本文创建 general_search 模式的图片库,该模式同时支持以图搜图和以文搜图两种检索方式。
效果预览
跟随本文,您将基于图片搜索 API 搭建一个同时支持以文搜图和以图搜图的检索系统。由于响应体仅返回 image_uri 和相似度分数,以下先直观展示两种检索方式的最终效果。
以文搜图:输入文本 a macbook,返回语义最相关的图片。

以图搜图:输入一张查询图片,返回视觉最相似的图片。

前提条件
开始前,请确认已完成以下准备工作:
已创建 AnalyticDB for MySQL 集群。
已开通图片搜索服务。
重要图片搜索功能当前处于邀测阶段。如需使用,请提交工单或联系技术支持申请开通。
已准备 OSS Bucket,且 Bucket 与 AnalyticDB for MySQL 集群在同一地域。OSS 用于存放示例图片和批量导入所需的 JSONL 文件。
本地已安装 Python 3 和 curl。
示例中使用以下环境变量,请根据实际环境替换:
export IMAGE_SEARCH_ENDPOINT="http://<host>:<port>"
export API_PREFIX="$IMAGE_SEARCH_ENDPOINT/api/v1/operators/image-search"
export OSS_BUCKET="<YOUR-BUCKET-NAME>"
export OSS_PREFIX="image-search/picsum"
export LIBRARY_NAME="picsum_general_search"
变量 | 说明 |
| 图片搜索服务的访问地址。开通服务后,可在 AnalyticDB for MySQL 控制台获取。 |
| OSS Bucket 名称,需与集群在同一地域。 |
| 示例数据在 OSS 中的存放路径前缀。 |
| 本文创建的示例图片库名称。 |
步骤一:准备并上传示例图片
本文使用 Lorem Picsum 提供的公开图片。Lorem Picsum 提供图片列表 API,可按分页获取图片元数据。本示例下载其中 100 张固定尺寸(800×600)的图片用于演示。
创建 prepare_picsum_data.py,用于下载图片并生成批量导入所需的 JSONL 文件:
import json
import urllib.request
from pathlib import Path
# 输出目录和文件
ROOT = Path(".")
IMAGE_DIR = ROOT / "images"
OUTPUT_FILE = ROOT / "import_task.jsonl"
# 图片在 OSS 中的路径前缀
IMAGE_PREFIX = "image-search/picsum/images"
# Lorem Picsum 公开 API
LIST_URL = "https://picsum.photos/v2/list?page=1&limit=100"
IMAGE_SIZE = "800/600"
IMAGE_DIR.mkdir(exist_ok=True)
# 获取图片列表
with urllib.request.urlopen(LIST_URL) as resp:
items = json.loads(resp.read().decode("utf-8"))
# 生成 JSONL 文件
with OUTPUT_FILE.open("w", encoding="utf-8") as out:
for index, item in enumerate(items, start=1):
source_id = int(item["id"])
image_id = f"picsum_{source_id:06d}"
file_name = f"{image_id}.jpg"
local_path = IMAGE_DIR / file_name
image_url = f"https://picsum.photos/id/{source_id}/{IMAGE_SIZE}"
# 下载图片到本地
if not local_path.exists():
print(f"正在下载 {image_url}")
urllib.request.urlretrieve(image_url, local_path)
# 写入 JSONL 记录
record = {
"image_id": image_id,
"image_uri": f"{IMAGE_PREFIX}/{file_name}",
"action": "ADD",
"tags": {
"dataset": "picsum",
"source_id": source_id,
"author": item.get("author", ""),
"sample_index": index,
"width": 800,
"height": 600,
},
}
out.write(json.dumps(record, ensure_ascii=False) + "\n")
print(f"已生成 {OUTPUT_FILE}")
执行脚本并检查输出:
python3 prepare_picsum_data.py
head -n 3 import_task.jsonl
生成的 JSONL 文件中每行为一条 JSON 记录,格式如下:
{"image_id": "picsum_000000", "image_uri": "image-search/picsum/images/picsum_000000.jpg", "action": "ADD", "tags": {"dataset": "picsum", "source_id": 0, "author": "Alejandro Escamilla", "sample_index": 1, "width": 800, "height": 600}}
JSONL 记录中各字段说明如下:
字段 | 类型 | 说明 |
| string | 图片唯一标识。 |
| string | 图片在 OSS Bucket 中的对象路径。 |
| string | 操作类型, |
| object | 自定义标签键值对,用于检索时的过滤。 |
将 images/ 目录下的图片和 import_task.jsonl 文件上传到同一个 OSS Bucket。上传可通过 OSS 控制台、ossutil 或 OSS SDK 完成。
上传完成后,请确认 OSS 中存在以下对象:
image-search/picsum/images/picsum_000000.jpg
image-search/picsum/import_task.jsonl
步骤二:创建图片库
创建
general_search模式的图片库,并声明后续入库和过滤会使用的标签字段。curl -X POST "$API_PREFIX/library/create" \ -H 'Content-Type: application/json' \ -d "{ \"library_name\": \"$LIBRARY_NAME\", \"mode\": \"general_search\", \"description\": \"Lorem Picsum public images for image search demo\", \"tag_schema\": [ {\"name\": \"dataset\", \"type\": \"string\"}, {\"name\": \"source_id\", \"type\": \"int\"}, {\"name\": \"author\", \"type\": \"string\"}, {\"name\": \"sample_index\", \"type\": \"int\"}, {\"name\": \"width\", \"type\": \"int\"}, {\"name\": \"height\", \"type\": \"int\"} ] }"创建请求提交成功后,返回结果示例如下:
{ "status": "SUCCESS", "message": null, "data": { "library_name": "picsum_general_search", "status": "initing" } }data.status为initing表示图片库正在初始化。初始化完成后状态会变为ready。图片库创建后不能修改工作模式和标签字段,如需调整,请删除后重新创建。调用图片库列表接口,确认目标图片库状态为
ready后再继续后续操作。curl -X GET "$API_PREFIX/library/list"返回结果示例:
{ "status": "SUCCESS", "message": null, "data": { "total": 1, "libraries": [ { "library_name": "picsum_general_search", "mode": "general_search", "image_count": 0, "status": "ready", "message": null, "description": "Lorem Picsum public images for image search demo" } ] } }说明如果目标图片库的
status仍为initing,请等待后重试。如果为failed,请查看返回的message字段获取失败原因,并重新创建图片库。
步骤三:导入图片
使用 OSS 上的 JSONL 文件创建异步批量导入任务:
curl -X POST "$API_PREFIX/image/tasks/create" \
-H 'Content-Type: application/json' \
-d "{
\"library_name\": \"$LIBRARY_NAME\",
\"meta_file_uri\": \"oss://$OSS_BUCKET/$OSS_PREFIX/import_task.jsonl\",
\"save_image\": false
}"
成功后返回任务 ID:
{
"status": "SUCCESS",
"message": null,
"data": {
"task_id": "task_x9y8z7w6v5"
}
}
记录返回的 task_id,使用该 ID 查询导入进度:
export TASK_ID="task_x9y8z7w6v5"
curl -X GET "$API_PREFIX/image/tasks/results/$TASK_ID"
当任务完成且全部图片处理成功时,返回结果示例如下:
{
"status": "SUCCESS",
"message": null,
"data": {
"task_id": "task_x9y8z7w6v5",
"task_status": "SUCCESS",
"total": 100,
"processed": 100,
"failed_count": 0,
"message": null
}
}
本文将 save_image 设置为 false,检索结果中不返回图片的 Base64 原始数据,仅返回 image_uri、相似度分数和标签信息。如需在检索结果中直接返回图片内容,请设置为 true。
如果 failed_count 大于 0,请依次检查以下内容:
JSONL 文件格式是否正确(每行一条 JSON 记录)。
image_uri路径对应的图片是否已上传到 OSS。图片搜索服务是否具有读取 OSS 对象的权限。
标签字段是否与创建图片库时声明的
tag_schema一致。
步骤四:以文搜图
创建请求生成脚本 search_by_text.py,用于构造以文搜图的请求体:
import json
import os
import sys
query_text = " ".join(sys.argv[1:]) or "a macbook"
payload = {
"library_name": os.environ.get("LIBRARY_NAME", "picsum_general_search"),
"query_text": query_text,
"top_k": 3,
"tag_filter": [
{"field": "dataset", "op": "=", "value": "picsum"},
],
"return_frame": False,
}
print(json.dumps(payload, ensure_ascii=False))
执行以文搜图请求:
python3 search_by_text.py "a macbook" | \
curl -X POST "$API_PREFIX/search/by-text" \
-H 'Content-Type: application/json' \
-d @-
响应中 results 按相似度分数从高到低排列。以查询文本 a macbook 为例,返回的图片如下:

请求参数说明:
参数 | 说明 |
| 搜索文本描述。支持多语言输入。 |
| 返回的最大结果数量,默认为 10。 |
| 标签过滤条件,支持精确匹配、包含匹配和逻辑组合(AND/OR)。 |
| 是否在结果中返回图片的 Base64 编码内容。设为 |
返回结果中的 tags 会包含图片库的完整标签列,除创建图片库时声明的标签字段外,也可能包含 int_tag1 至 int_tag5、str_tag1 至 str_tag5 等内部预留标签字段,未写入值的字段通常为 null。业务展示时可以忽略这些预留字段。
步骤五:以图搜图
创建请求生成脚本 search_by_image.py,用于读取本地图片并构造以图搜图的请求体:
import base64
import json
import os
import sys
from pathlib import Path
query_image = Path(sys.argv[1])
payload = {
"library_name": os.environ.get("LIBRARY_NAME", "picsum_general_search"),
"image_base64": base64.b64encode(query_image.read_bytes()).decode("utf-8"),
"top_k": 3,
"tag_filter": [
{"field": "dataset", "op": "=", "value": "picsum"},
],
"return_frame": False,
}
print(json.dumps(payload, ensure_ascii=False))
执行以图搜图请求:
python3 search_by_image.py images/picsum_000000.jpg | \
curl -X POST "$API_PREFIX/search/by-image" \
-H 'Content-Type: application/json' \
-d @-
本示例使用的查询图片如下:

成功响应示例:
{
"status": "SUCCESS",
"message": null,
"data": {
"results": [
{
"image_id": "picsum_000000",
"image_uri": "image-search/picsum/images/picsum_000000.jpg",
"image_base64": null,
"score": 1.0000,
"tags": {
"dataset": "picsum",
"source_id": 0,
"author": "Alejandro Escamilla",
"sample_index": 1,
"width": 800,
"height": 600
}
}
]
}
}
服务返回的视觉最相似图片如下(Top-K):

如果查询图片本身在图片库中,通常会优先返回自身(相似度分数为 1.0)或高度相似的图片。如果查询图片不在图片库中,服务会返回视觉或语义上最接近的图片。
清理资源
如不再需要示例图片库,可删除图片库释放资源:
curl -X POST "$API_PREFIX/library/delete" \
-H 'Content-Type: application/json' \
-d "{
\"library_name\": \"$LIBRARY_NAME\"
}"
删除图片库会同时删除库内所有图片数据,操作不可恢复。OSS 上的图片文件和 JSONL 文件不会被自动删除,如需释放 OSS 存储空间,请单独清理。