在电商铺货过程中,每天都会新增几十甚至几百个新品。由于产品数量众多,难免会遇到相同的SKU。为了避免重复上架,我们需要用到深度学习算法进行图片相似度比较,实现类似Google Lens的效果。
今天要用到的模型和算法:
- Faster R-CNN
- OpenAI CLIP
- Cosine Similarity
在之前的文章中提到,余弦相似度(Cosine Similarity)在数据科学中可以被用来比较两个向量之间的相关性,从而达到相似度对比。详情可以看Phil Miesle的Exploring the Real-world Applications of Cosine Similarity
什么是Faster R-CNN?
Faster R-CNN(Region-based Convolutional Neural Network)是一种应用于对象检测(Object Detection)任务的深度学习模型。Faster R-CNN 通过引入区域建议网络(RPN),提高了对象检测的速度和准确性。RPN 生成一系列候选区域,这些区域随后由 Fast R-CNN 检测器进行分类和边界框回归,从而确定每个对象的类别和精确位置。
Faster R-CNN 的工作流程如下:
- 特征提取:使用卷积神经网络(如 ResNet)从输入图像中提取特征。
- 区域建议:RPN 生成可能包含对象的候选区域(Anchor)。
- 区域分类和回归:Fast R-CNN 检测器对这些候选区域进行分类,并精确调整边界框的位置。
model = models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
def detect_objects(image):
with torch.no_grad():
prediction = model([transform(image)])[0]
return prediction
用fasterrcnn_resnet50_fpn进行预测,会输出由以下元素组成的Python dictionary:
boxes: 输出包含[y_min, x_min, y_max, x_max]的张量(Tensor). 可以理解为图片中的框框
labels: 输出由整数组成的张量,如tensor([28, 63, 64, 62, 28]). 这些整数代表了训练数据集的类目,由于fasterrcnn_resnet50_fpn是从COCO数据集训练的,数字对应的类别可以参考:https://github.com/amikelive/coco-labels/blob/master/coco-labels-paper.txt
scores: 每个框框的置信度(confidence score), 代表了框框中的object和预测类目的相似度
以Aosom.com的场景图片作为例子,以下是模型输出后的boxes:
在不加任何限制条件时,模型会输出检测到的所有框框。假设我们现在的任务是匹配沙发的相似度,在coco-labels-paper.txt中找到63 = couch (沙发),那我们就可以在boxes中匹配labels = 63的box:
def extract_main_object(image, prediction, target_label=63):
boxes = prediction['boxes']
scores = prediction['scores']
labels = prediction['labels']
# 筛选出标签为沙发的框框
valid_boxes = boxes[labels == target_label]
valid_scores = scores[labels == target_label]
if len(valid_boxes) > 0:
# 获取置信度最高的框框
max_score_idx = valid_scores.argmax()
x1, y1, x2, y2 = valid_boxes[max_score_idx].int().numpy()
return image.crop((x1, y1, x2, y2))
return image
什么是OpenAI CLIP?
CLIP 通过多模态对比学习(Contrastive Learning)来训练(text image pairs),在训练时同时学习了大量图像和文本,CLIP 能够捕捉更丰富的语义信息,从而在图像向量表示中包含更多的上下文和语义信息 。CLIP拥有不错的零样本学习能力(Zero Shot Learning),也就是说我们可以直接通过预训练模型进行预测:
clip_model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
# 使用上文预测的main_object
inputs = clip_processor(images=main_object, return_tensors="pt")
with torch.no_grad():
image_features = clip_model.get_image_features(**inputs)
模型会输出这个图像的嵌入(embeddings):
tensor([[-2.9532e-01, 2.1558e-01, 4.4454e-02, -3.7444e-01, 3.6188e-01, -1.9132e-01, -2.2710e-01, 4.9299e-01, -4.9231e-02, -1.9174e-01, 5.0825e-01, 1.1113e-01, -4.0802e-02, -5.4021e-01, 3.3626e-01, -7.0196e-02, -5.7222e-01, -2.7112e-02, 1.4611e-01, -1.1657e-02, 4.0651e-01, 1.7071e-01, 1.5620e-01, … -8.3940e-02]])
余弦相似度 Cosine Similarity:
回归最经典的余弦相似度进行两张图对比:
from sklearn.metrics.pairwise import cosine_similarity
similarities = cosine_similarity(image_features, target_image_features)
轻松找到重合产品:
图片1:Credenza con Motivo a Spina di Pesce
图片2:HOMCOM Credenza Moderna in Truciolato e Metallo con 2 Armadietti a 2 Ante con Ripiani e 3 Cassetti
相似度:94.8%
Faster R-CNN裁剪出方框,有没有更精准的裁剪算法?
有,Mask R-CNN 在 Faster R-CNN 的基础上增加了一个用于实例分割的分支,能够为每个对象生成像素级的分割掩码。Mask R-CNN 优势在于实例分割能力,能够提供对象的精确边界,而不仅仅是边界框。这对于需要精确对象形状信息的任务(如医学图像分析、自动驾驶中的障碍物检测)尤为重要。
原图:
通过maskrcnn_resnet50_fpn检测主体并裁切后的图片:
Mask R-CNN能更加精确的识别主体。但需要注意的是,Mask的算法需要更长时间。在电商铺品这个环境下,需要找到两者之间的平衡。