AI与Milvus结合推动时尚应用发展 -- 知识铺
寻找与自己穿搭风格相似的明星
在上一篇文章中,我们探索了如何使用人工智能技术,特别是开源AI向量数据库Milvus和Hugging Face模型,来寻找与自己穿搭风格相似的明星。本文将进一步介绍如何对项目代码进行微调,以获得更详细和准确的结果,并在文末提供彩蛋。
项目代码微调
1. 代码获取首先,需要获取项目使用到的图片,可以通过以下链接下载:图片下载链接
2. 环境准备使用Jupyter Notebook来运行项目,可以通过以下链接直接打开:Jupyter Notebook
3. 代码修改对上篇文章中的项目代码进行必要的修改,以提高结果的准确性和详细程度。具体修改方法将在下文中详细说明。
彩蛋文末附赠的彩蛋将为读者带来更多惊喜,敬期待。
本文内容是对上一篇文章的延伸,旨在帮助读者更深入地理解和应用AI技术于时尚领域。
图像处理库导入与使用指南
概述
在进行图像处理任务之前,我们需要导入一系列必要的库和工具。本文将详细介绍如何导入这些库,并简要说明它们的作用。
导入图像处理库
以下是进行图像处理所需导入的主要库列表:
- torch: 用于深度学习的特征提取。
- transformers: 包含
segformer
对象,用于图像分割任务。 - matplotlib: 用于数据可视化。
- torchvision: 包含
Resize
、masks_to_boxes
和crop
等工具,用于图像的预处理和操作。
导入步骤1. 首先,确保你的环境中已经安装了上述库。如果没有,可以使用pip命令进行安装。2. 使用import
语句导入所需的库。例如: python import torch from transformers import Segformer import matplotlib.pyplot as plt from torchvision import transforms
3. 根据你的项目需求,选择合适的工具和函数进行图像处理。
注意事项
- 确保导入的库版本与你的项目兼容,以避免潜在的兼容性问题。
- 在使用
segformer
等高级对象时,需要先了解其使用方法和参数配置。
结语通过上述步骤,你可以顺利地导入并使用所需的图像处理库。希望本文能够帮助你在图像处理项目中取得成功。
import torch
from torch import nn, tensor
from transformers import AutoFeatureExtractor, SegformerForSemanticSegmentation
import matplotlib.pyplot as plt
from torchvision.transforms import Resize
import torchvision.transforms as T
from torchvision.ops import masks_to_boxes
from torchvision.transforms.functional import crop
- 预处理明星照片
在导入所有必要的图像处理库和工具后,就可以开始处理图像。以下三个函数 get_segmentation、get_masks 和 crop_images 用于分割并裁剪图片中的时尚单品,以供后续使用。
import torch
def get_segmentation(extractor, model, image):
inputs = extractor(images=image, return_tensors="pt")
outputs = model(**inputs)
logits = outputs.logits.cpu()
upsampled_logits = nn.functional.interpolate(
logits,
size=image.size[::-1],
mode="bilinear",
align_corners=False,
)
pred_seg = upsampled_logits.argmax(dim=1)[0]
return pred_seg
# 返回两个 masks(tensor)列表和 obj_ids(int)
# 来自 Hugging Face 的 mattmdjaga/segformer_b2_clothes 模型
def get_masks(segmentation):
obj_ids = torch.unique(segmentation)
obj_ids = obj_ids[1:]
masks = segmentation == obj_ids[:, None, None]
return masks, obj_ids
def crop_images(masks, obj_ids, img):
boxes = masks_to_boxes(masks)
crop_boxes = []
for box in boxes:
crop_box = tensor([box[0], box[1], box[2]-box[0], box[3]-box[1]])
crop_boxes.append(crop_box)
preprocess = T.Compose([
T.Resize(size=(256, 256)),
T.ToTensor()
])
cropped_images = {}
for i in range(len(crop_boxes)):
crop_box = crop_boxes[i]
cropped = crop(img, crop_box[1].item(), crop_box[0].item(), crop_box[3].item(), crop_box[2].item())
cropped_images[obj_ids[i].item()] = preprocess(cropped)
return cropped_images
import os
image_paths = []
for celeb in os.listdir("./photos"):
for image in os.listdir(f"./photos/{celeb}/"):
image_paths.append(f"./photos/{celeb}/{image}")
from milvus import default_server
from pymilvus import utility, connections
default_server.start()
connections.connect(host="127.0.0.1", port=default_server.listen_port)
DIMENSION = 2048
BATCH_SIZE = 128
COLLECTION_NAME = "fashion"
TOP_K = 3
from pymilvus import FieldSchema, CollectionSchema, Collection, DataType
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name='filepath', dtype=DataType.VARCHAR, max_length=200),
FieldSchema(name="name", dtype=DataType.VARCHAR, max_length=200),
FieldSchema(name="seg_id", dtype=DataType.INT64),
FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, dim=DIMENSION)
]
schema = CollectionSchema(fields=fields)
collection = Collection(name=COLLECTION_NAME, schema=schema)
index_params = {
"index_type": "IVF_FLAT",
"metric_type": "L2",
"params": {"nlist": 128},
}
collection.create_index(field_name="embedding", index_params=index_params)
collection.load()
接着,运行以下代码,使用来自 Hugging Face 的 Nvidia ResNet 50 模型生成 embedding 向量。
# 如遇 SSL 证书 URL 错误,请在导入 resnet50 模型前运行此步骤
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# 并删除最后一层模型输出
embeddings_model = torch.hub.load('NVIDIA/DeepLearningExamples:torchhub', 'nvidia_resnet50', pretrained=True)
embeddings_model = torch.nn.Sequential(*(list(embeddings_model.children())[:-1]))
embeddings_model.eval()
以下函数定义了如何将图像转换为向量并插入到 Milvus 向量数据库中。代码会循环遍历所有图像。(注意:如果需要开启 Milvus 全新特性动态 Schema,需要修改代码。)
def embed_insert(data, collection, model):
with torch.no_grad():
output = model(torch.stack(data[0])).squeeze()
collection.insert([data[1], data[2], data[3], output.tolist()])
from PIL import Image
data_batch = [[], [], [], []]
for path in image_paths:
image = Image.open(path)
path_split = path.split("/")
name = " ".join(path_split[2].split("_"))
segmentation = get_segmentation(extractor, model, image)
masks, ids = get_masks(segmentation)
cropped_images = crop_images(masks, ids, image)for key, image in cropped_images.items():
data_batch[0].append(image)
data_batch[1].append(path)
data_batch[2].append(name)
data_batch[3].append(key)
if len(data_batch[0]) % BATCH_SIZE == 0:
embed_insert(data_batch, collection, embeddings_model)
data_batch = [[], [], [], []]
if len(data_batch[0]) != 0:
embed_insert(data_batch, collection, embeddings_model)
collection.flush()
- 查询向量数据库
以下代码演示了如何使用输入图像查询 Milvus 向量数据库,以检索和上传衣服图像最相似的的前三个结果。
def embed_search_images(data, model):
with torch.no_grad():
output = model(torch.stack(data))
if len(output) > 1:
return output.squeeze().tolist()
else:
return torch.flatten(output, start_dim=1).tolist()
# data_batch[0]是 tensor 列表
# data_batch[1]是图像文件的文件路径(字符串)
# data_batch[2]是图像中人物的名称列表(字符串)
# data_batch[3]是分割键值列表(int)
data_batch = [[], [], [], []]
search_paths = ["./photos/Taylor_Swift/Taylor_Swift_3.jpg", "./photos/Taylor_Swift/Taylor_Swift_8.jpg"]
for path in search_paths:
image = Image.open(path)
path_split = path.split("/")
name = " ".join(path_split[2].split("_"))
segmentation = get_segmentation(extractor, model, image)
masks, ids = get_masks(segmentation)
cropped_images = crop_images(masks, ids, image)
for key, image in cropped_images.items():
data_batch[0].append(image)
data_batch[1].append(path)
data_batch[2].append(name)
data_batch[3].append(key)
embeds = embed_search_images(data_batch[0], embeddings_model)
import time
start = time.time()
res = collection.search(embeds,
anns_field='embedding',
param={"metric_type": "L2",
"params": {"nprobe": 10}},
limit=TOP_K,
output_fields=['filepath'])
finish = time.time()
print(finish - start)
for index, result in enumerate(res):
print(index)
print(result)
扩展图像识别项目的应用场景
在原有图像识别项目的基础上,我们可以通过修改代码来实现更广泛的应用。本节将介绍如何通过调整代码,实现识别图像中的时尚单品,而不仅仅是明星的着装风格。
1. 调整代码以识别时尚单品
首先,我们需要对现有代码进行一些调整,以便它能够识别图像中的时尚元素。这可能包括衣服、配饰、鞋子等。通过分析图像并识别这些元素,我们可以为用户提供更个性化的时尚建议。
2. 获取不包含边界框的图像
进一步地,我们可以修改代码来获取不包含边界框的图像。这意味着图像中的时尚单品将被直接展示,而不是通过边界框来标示。这样的展示方式可以让用户更直观地看到单品的细节。
3. 应用场景拓展
- 个性化推荐:根据用户喜好和图像识别结果,为用户提供个性化的时尚单品推荐。
- 时尚趋势分析:通过收集大量图像数据,分析当前流行的时尚趋势。
- 虚拟试衣间:结合3D技术,让用户在虚拟环境中试穿识别出的时尚单品。
4. 技术实现要点
- 图像处理:使用图像处理技术来增强对时尚单品的识别能力。
- 机器学习:利用机器学习算法来提高识别的准确性和效率。
- 用户界面:设计直观易用的用户界面,提升用户体验。
通过这些步骤,我们的项目不仅能够识别明星的着装风格,还能够扩展到更广泛的时尚领域,为用户提供更加丰富的服务。
接下来,将为大家介绍如何修改上述代码寻找更多匹配的穿衣风格。
- 导入所需的图像处理库和工具
同样,需要先导入所有必要的图像处理库。如果已经完成导入,请跳过此步骤。
import torch
from torch import nn, tensor
from transformers import AutoFeatureExtractor, SegformerForSemanticSegmentation
import matplotlib.pyplot as plt
from torchvision.transforms import Resize
import torchvision.transforms as T
from torchvision.ops import masks_to_boxes
from torchvision.transforms.functional import crop
在图像预处理的流程中,我们主要关注三个关键步骤:分割、掩膜提取和图像裁剪。以下是针对这些步骤的详细说明和代码调整建议:
- 分割图像获取 (
get_segmentation
函数)
- 无需对
get_segmentation
函数进行修改,保持其原有功能,用于获取图像的分割信息。
- 掩膜提取 (
get_masks
函数)
- 调整
get_masks
函数,使其仅提取与wanted
列表中指定的分割 ID 相对应的掩膜图像。
- 图像裁剪 (
crop_images
函数)
- 对
crop_images
函数进行重要调整,以适应新的流程需求。原函数仅返回裁剪后的图像列表,现在需要返回三个对象: - Embedding 向量:裁剪图像对应的特征向量,这将优化后续的数据处理流程。
- 边界框坐标:原始图像上边界框的坐标列表,用于定位裁剪图像的原始位置。
- 分割 ID 列表:与裁剪图像相对应的分割 ID 列表,以便于后续处理和分析。 通过这些调整,我们能够更有效地处理图像数据,为后续的分析和应用打下坚实的基础。
wanted = [1, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17]
def get_segmentation(image):
inputs = extractor(images=image, return_tensors="pt")
outputs = segmentation_model(**inputs)
logits = outputs.logits.cpu()
upsampled_logits = nn.functional.interpolate(
logits,
size=image.size[::-1],
mode="bilinear",
align_corners=False,
)
pred_seg = upsampled_logits.argmax(dim=1)[0]
return pred_seg
# returns two lists masks (tensor) and obj_ids (int)
# "mattmdjaga/segformer_b2_clothes" from hugging face
def get_masks(segmentation):
obj_ids = torch.unique(segmentation)
obj_ids = obj_ids[1:]
wanted_ids = [x.item() for x in obj_ids if x in wanted]
wanted_ids = torch.Tensor(wanted_ids)
masks = segmentation == wanted_ids[:, None, None]
return masks, obj_ids
def crop_images(masks, obj_ids, img):
boxes = masks_to_boxes(masks)
crop_boxes = []
for box in boxes:
crop_box = tensor([box[0], box[1], box[2]-box[0], box[3]-box[1]])
crop_boxes.append(crop_box)
preprocess = T.Compose([
T.Resize(size=(256, 256)),
T.ToTensor()
])
cropped_images = []
seg_ids = []
for i in range(len(crop_boxes)):
crop_box = crop_boxes[i]
cropped = crop(img, crop_box[1].item(), crop_box[0].item(), crop_box[3].item(), crop_box[2].item())
cropped_images.append(preprocess(cropped))
seg_ids.append(obj_ids[i].item())
with torch.no_grad():
embeddings = embeddings_model(torch.stack(cropped_images)).squeeze().tolist()
return embeddings, boxes.tolist(), seg_ids
有了图像数据之后,就可以加载数据了。这一步骤需要使用到批量插入功能,上篇文章的教程中也有涉及,但不同点在于,本文的教程中将数据作为 dictionary 列表一次性插入。这种插入方式更简洁,同时还允许我们在插入数据时动态新增 Schema 字段。
for path in image_paths:
image = Image.open(path)
path_split = path.split("/")
name = " ".join(path_split[2].split("_"))
segmentation = get_segmentation(image)
masks, ids = get_masks(segmentation)
embeddings, crop_corners, seg_ids = crop_images(masks, ids, image)
inserts = [{"embedding": embeddings[x], "seg_id": seg_ids[x], "name": name, "filepath": path, "crop_corner": crop_corners[x]} for x in range(len(embeddings))]
collection.insert(inserts)
collection.flush()
向量数据库Milvus查询教程
本文将介绍如何在向量数据库Milvus中进行数据查询,并对查询结果进行可视化展示。本教程与上一篇教程相比,有以下主要区别:
1. 查询限制
- 将图像中匹配的时尚单品数量限制为5件。
2. 查询返回结果
- 指定查询返回最相似的3张图像。
3. 图像色彩图获取
- 添加了获取图片色彩图的函数。
可视化展示在matplotlib中设置figures和axes,通过循环遍历所有图像,应用以下3个函数:
- 应用分割结果函数
- 应用边界框函数
- 应用色彩图函数
步骤说明
- 设置环境:在matplotlib中创建必要的图形和坐标轴。
- 循环遍历图像:对每张图像应用上述函数,以获取分割结果和边界框。
- 查询数据:根据每张图像中匹配的时尚单品数量,获取最相似的3张图像。
- 结果展示:最终返回的结果图像将展示带有边界框的匹配单品。
注意事项
- 确保查询结果的准确性,边界框应清晰标示出匹配的单品。 通过以上步骤,用户可以有效地在Milvus中查询数据,并对查询结果进行可视化展示。
from pprint import pprint
from PIL import ImageDraw
from collections import Counter
import matplotlib.patches as patches
LIMIT = 5 # 每张图像中匹配的时尚单品件数
CLOSEST = 3 # 返回的最相似图像数量。CLOSEST <= Limit
search_paths = ["./photos/Taylor_Swift/Taylor_Swift_2.jpg", "./photos/Jenna_Ortega/Jenna_Ortega_6.jpg"] # Images to search fordef get_cmap(n, name='hsv'):
'''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct
RGB color; the keyword argument name must be a standard mpl colormap name.
Sourced from <https://stackoverflow.com/questions/14720331/how-to-generate-random-colors-in-matplotlib>'''return plt.cm.get_cmap(name, n)
# 创建结果 subplot
f, axarr = plt.subplots(max(len(search_paths), 2), CLOSEST + 1)
for search_i, path in enumerate(search_paths):
# Generate crops and embeddings for all items found
image = Image.open(path)
segmentation = get_segmentation(image)
masks, ids = get_masks(segmentation)
embeddings, crop_corners, _ = crop_images(masks, ids, image)
# 生成色彩图
cmap = get_cmap(len(crop_corners))
# Display the first box with image being searched for
axarr[search_i][0].imshow(image)
axarr[search_i][0].set_title('Search Image')
axarr[search_i][0].axis('off')
for i, (x0, y0, x1, y1) in enumerate(crop_corners):
rect = patches.Rectangle((x0, y0), x1-x0, y1-y0, linewidth=1, edgecolor=cmap(i), facecolor='none')
axarr[search_i][0].add_patch(rect)
# 查询向量数据库
start = time.time()
res = collection.search(embeddings,
anns_field='embedding',
param={"metric_type": "L2",
"params": {"nprobe": 10}, "offset": 0},
limit=LIMIT,
output_fields=['filepath', 'crop_corner'])
finish = time.time()
print("Total Search Time: ", finish - start)
# 根据位置给查询结果增加不同的权重
filepaths = []
for hits in res:
seen = set()
for i, hit in enumerate(hits):
if hit.entity.get("filepath") not in seen:
seen.add(hit.entity.get("filepath"))
filepaths.extend([hit.entity.get("filepath") for _ in range(len(hits) - i)])
# 查找排名最高的图像
counts = Counter(filepaths)
most_common = [path for path, _ in counts.most_common(CLOSEST)]
# 提取每张图像中与查询图像相关的时尚单品
matches = {}
for i, hits in enumerate(res):
matches[i] = {}
tracker = set(most_common)
for hit in hits:
if hit.entity.get("filepath") in tracker:
matches[i][hit.entity.get("filepath")] = hit.entity.get("crop_corner")
tracker.remove( hit.entity.get("filepath"))
# 返回最相似图像:
# 返回与查询图像临近的图像
image = Image.open(res_path)
axarr[search_i][res_i+1].imshow(image)
axarr[search_i][res_i+1].set_title(" ".join(res_path.split("/")[2].split("_")))
axarr[search_i][res_i+1].axis('off')
# 为匹配单品添加边界框
if res_path in value:
x0, y0, x1, y1 = value[res_path]
rect = patches.Rectangle((x0, y0), x1-x0, y1-y0, linewidth=1, edgecolor=cmap(key), facecolor='none')
axarr[search_i][res_i+1].add_patch(rect)
运行上述步骤后,结果如下所示:
项目后续:探索更多应用场景
1. 扩展对比功能
- 将不同单品进行归类对比,丰富数据库中的图像资源,以提供更多样化的查询结果。
2. 时尚探测与推荐系统
- 利用明星图像转换为可购买衣服的图像,实现用户上传照片后,系统推荐风格相似的衣物。 ### 3. 穿搭生成系统
- 构建一个系统,根据用户上传的多张照片推荐穿搭,使用生成式图像模型提供穿搭建议,实现难度较高。
总结
1. 教程回顾
- 本文教程扩展了时尚 AI 项目的应用场景,利用 Milvus 的动态 Schema 功能筛选分割 ID 并保留边界框,在查询中根据时尚单品件数返回最相似的图像。
2. 动态 Schema 功能
- Milvus 的动态 Schema 功能允许在上传数据时添加新字段,简化了批量上传数据的过程,并在预处理中剔除非着装类元素。
3. 进一步应用搭建
- 通过代码调整,可以构建时尚推荐系统、用户着装搭配系统,以及生成式时尚 AI 应用。
专题活动预告
- 「寻找 AIGC 时代的 CVP 实践之星」 专题活动即将启动,Zilliz 将联合国内大模型厂商,提供向量数据库与大模型技术支持,共同提升应用落地效果。
参与方式
- 如果你的应用适合 CVP 框架并寻求专业帮助,可通过邮箱 business@zilliz.com 申请参与活动。
本文作者
- 作者信息待补充。
唐玉剑
Zilliz 开发者布道师
推荐阅读
[
LLM 落地电商行业的最佳实践来了?Zilliz X AWS 有话说
活动背景大模型技术正加速改革和重塑各行各业,电商行业因其高度数字化成为大模型应用的绝佳领域。向量数据库和云计算是大模型落地的基石。
活动介绍Zilliz 联合亚马逊云科技举办活动,探讨大模型在电商行业的应用场景、方案解析和最佳实践。
活动议程
- 活动日期:2023年9月7日 13:30-17:00
- 活动地点:上海市黄浦区河南中路88号外滩中心威斯汀大饭店
议题概览
- 电商场景构建 GenAI 应用实践分享
- 李雪晴
- 探讨基于亚马逊云科技产品构建 GenAI 应用的方法。
- 向量数据库在电商及大模型领域应用方案介绍
- 沈亮
- 介绍向量数据库的基本概念、功能和电商领域应用。
- 得物基于向量数据库 Milvus 的大模型应用实践
- 孟令公
- 分享得物构建大模型训练推理平台的经验。
- 基于智能搜索和大语言模型打造下一代企业知识库
- 熊俊峰
- 介绍如何使用智能搜索和大语言模型构建企业知识库。
- Cupshe 如何基于向量检索和 AI 技术构建电商智能搜索方案
- 吴万涛
- 讨论如何结合关键词搜索和向量语义搜索优化电商搜索结果。
- CVP 讲堂—— 0-1 搭建电商行业知识库应用
- 陈将
- 介绍如何使用向量数据库和大语言模型搭建智能问答机器人。
专题活动Zilliz 将联合大模型厂商甄选应用场景,提供技术专家支持,共同提升应用落地效果。
联系方式感兴趣的应用开发者可以联系:business@zilliz.com 参与活动。
推荐阅读
当一个程序员决定穿上粉色裤子
作为一个大众眼中的“非典型程序员”,作者喜欢拥抱时尚和潮流,经常在演讲时穿粉色裤子,这已成为他的标志性打扮。某天,作者突发奇想,想借助Milvus找到一个与自己穿搭风格最为相似的明星。
项目背景
最近,作者遇到了一个名为Fashion AI的项目,该项目利用微调模型对服装图片进行分割,然后裁剪出标注的时尚单品,并将图片转化为embedding向量存储在Milvus数据库中。通过上传自己穿着打扮的照片,可以查询到与自己时尚风格最相似的明星。
实现路径
1. 图像分割作者在Hugging Face上找到了segformer模型,该模型可以对不同的服装图片进行准确分割,并识别出18种对象类型。通过编写get_segmentation
函数,可以生成18层的图像分割掩膜。
2. 裁剪和调整图像大小使用get_masks
函数为图像中每个监测到的对象生成新图像,并调整图像大小。
3. 向量数据库存储将裁剪后的图像添加至Milvus向量数据库中,使用PyMilvus连接至Milvus Lite版本,并创建Collection。
4. 获取embedding向量使用Nvidia提供的ResNet50模型,删除最后一层输出,以获取embedding向量。
5. 寻找相似明星上传图片转化为向量后,在Milvus数据库中查询相似数据,返回最相似的3个明星。
结语作者鼓励大家尝试这个项目,并分享自己的结果。
’ fill=’%23FFFFFF’%3E%3Crect x=‘249’ y=‘126’ width=‘1’ height=‘1’%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek001/post/20240730/AI%E4%B8%8EMilvus%E7%BB%93%E5%90%88%E6%8E%A8%E5%8A%A8%E6%97%B6%E5%B0%9A%E5%BA%94%E7%94%A8%E5%8F%91%E5%B1%95--%E7%9F%A5%E8%AF%86%E9%93%BA/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com