开源 AI 食谱文档

使用多模态嵌入分析艺术风格

Hugging Face's logo
加入 Hugging Face 社区

并获得增强文档体验的访问权限

开始使用

Open In Colab

使用多模态嵌入分析艺术风格

作者:Jacob Marks

Art Analysis Cover Image

图像等视觉数据信息非常丰富,但其非结构化的性质使得分析变得困难。

在本笔记本中,我们将探索如何使用多模态嵌入和计算属性来分析图像中的艺术风格。我们将使用来自 🤗 Hub 的 WikiArt 数据集,将其加载到 FiftyOne 中进行数据分析和可视化。我们将以多种方式深入研究数据

  • 图像相似性搜索和语义搜索:我们将使用来自 🤗 Transformers 的预训练 CLIP 模型,为数据集中的图像生成多模态嵌入,并索引数据以允许进行非结构化搜索。

  • 聚类和可视化:我们将根据其艺术风格使用嵌入对图像进行聚类,并使用 UMAP 降维来可视化结果。

  • 唯一性分析:我们将使用嵌入根据图像与数据集中的其他图像的相似程度,为每个图像分配唯一性分数。

  • 图像质量分析:我们将计算每个图像的图像质量指标(如亮度、对比度和饱和度),并查看这些指标如何与图像的艺术风格相关联。

让我们开始吧!🚀

要运行此笔记本,您需要安装以下库

!pip install -U transformers huggingface_hub fiftyone umap-learn

要使下载速度更快,请安装 HF Transfer

pip install hf-transfer

并通过设置环境变量 HF_HUB_ENABLE_HF_TRANSFER 来启用

import os
os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"
注意:此笔记本在 transformers==4.40.0huggingface_hub==0.22.2fiftyone==0.23.8 上进行了测试。

现在让我们导入本笔记本需要的模块

import fiftyone as fo  # base library and app
import fiftyone.zoo as foz  # zoo datasets and models
import fiftyone.brain as fob  # ML routines
from fiftyone import ViewField as F  # for defining custom views
import fiftyone.utils.huggingface as fouh  # for loading datasets from Hugging Face

我们将从将 WikiArt 数据集从 🤗 Hub 加载到 FiftyOne 开始。此数据集也可以通过 Hugging Face 的 datasets 库加载,但我们将使用 FiftyOne 的 🤗 Hub 集成 直接从 Datasets 服务器获取数据。为了使计算速度更快,我们只下载前 $1,000$ 个样本。

dataset = fouh.load_from_hub(
    "huggan/wikiart",  ## repo_id
    format="parquet",  ## for Parquet format
    classification_fields=["artist", "style", "genre"],  # columns to store as classification fields
    max_samples=1000,  # number of samples to load
    name="wikiart",  # name of the dataset in FiftyOne
)

打印出数据集的摘要,以查看它包含的内容

>>> print(dataset)
Name:        wikiart
Media type:  image
Num samples: 1000
Persistent:  False
Tags:        []
Sample fields:
    id:       fiftyone.core.fields.ObjectIdField
    filepath: fiftyone.core.fields.StringField
    tags:     fiftyone.core.fields.ListField(fiftyone.core.fields.StringField)
    metadata: fiftyone.core.fields.EmbeddedDocumentField(fiftyone.core.metadata.ImageMetadata)
    artist:   fiftyone.core.fields.EmbeddedDocumentField(fiftyone.core.labels.Classification)
    style:    fiftyone.core.fields.EmbeddedDocumentField(fiftyone.core.labels.Classification)
    genre:    fiftyone.core.fields.EmbeddedDocumentField(fiftyone.core.labels.Classification)
    row_idx:  fiftyone.core.fields.IntField

FiftyOne 应用 中可视化数据集

session = fo.launch_app(dataset)

WikiArt Dataset

让我们列出我们将分析其风格的艺术家的姓名

>>> artists = dataset.distinct("artist.label")
>>> print(artists)
['Unknown Artist', 'albrecht-durer', 'boris-kustodiev', 'camille-pissarro', 'childe-hassam', 'claude-monet', 'edgar-degas', 'eugene-boudin', 'gustave-dore', 'ilya-repin', 'ivan-aivazovsky', 'ivan-shishkin', 'john-singer-sargent', 'marc-chagall', 'martiros-saryan', 'nicholas-roerich', 'pablo-picasso', 'paul-cezanne', 'pierre-auguste-renoir', 'pyotr-konchalovsky', 'raphael-kirchner', 'rembrandt', 'salvador-dali', 'vincent-van-gogh']

查找类似的艺术作品

当您找到一件喜欢的艺术品时,自然会想要找到类似的作品。我们可以使用向量嵌入来做到这一点!更重要的是,通过使用多模态嵌入,我们将解锁查找与给定文本查询非常相似的绘画的能力,这可能是绘画的描述,甚至是一首诗。

让我们使用来自 🤗 Transformers 的预训练 CLIP Vision Transformer (ViT) 模型为图像生成多模态嵌入。运行来自 FiftyOne Braincompute_similarity() 将计算这些嵌入并使用它们在数据集上生成相似性索引。

>>> fob.compute_similarity(
...     dataset,
...     model="zero-shot-classification-transformer-torch",  ## type of model to load from model zoo
...     name_or_path="openai/clip-vit-base-patch32",  ## repo_id of checkpoint
...     embeddings="clip_embeddings",  ## name of the field to store embeddings
...     brain_key="clip_sim",  ## key to store similarity index info
...     batch_size=32,  ## batch size for inference
... )
Computing embeddings...
 100% |███████████████| 1000/1000 [5.0m elapsed, 0s remaining, 3.3 samples/s]

或者,您可以直接从 🤗 Transformers 库加载模型,并将模型直接传入

from transformers import CLIPModel
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
fob.compute_similarity(
    dataset, 
    model=model,
    embeddings="clip_embeddings", ## name of the field to store embeddings
    brain_key="clip_sim" ## key to store similarity index info
)

有关此功能以及更多功能的全面指南,请查看 FiftyOne 的 🤗 Transformers 集成

刷新 FiftyOne 应用,选中样本网格中图像的复选框,然后单击照片图标以查看数据集中最相似的图像。在后台,单击此按钮将触发对相似性索引的查询,以根据预先计算的嵌入找到与所选图像最相似的图像,并在应用中显示它们。

Image Similarity Search

我们可以使用它来查看哪些艺术作品与给定的艺术作品最相似。这对于查找类似的艺术品(推荐给用户或添加到收藏中)或为新作品获得灵感非常有用。

但还有更多!由于 CLIP 是多模态的,因此我们也可以使用它执行语义搜索。这意味着我们可以根据文本查询搜索图像。例如,我们可以搜索“柔和的树木”,并查看数据集中所有与该查询相似的图像。为此,请在 FiftyOne 应用中单击搜索图标,然后输入文本查询

Semantic Search

在幕后,文本将被标记化,使用 CLIP 的文本编码器嵌入,然后用于查询相似性索引,以查找数据集中最相似的图像。这是一种根据文本查询搜索图像的强大方法,对于查找与特定主题或风格匹配的图像非常有用。这不仅限于 CLIP;您可以使用来自 🤗 Transformers 的任何类似 CLIP 的模型,该模型可以为图像和文本生成嵌入!

💡 对于大型数据集的有效向量搜索和索引,FiftyOne 与开源向量数据库具有原生 集成

使用聚类和可视化发现艺术主题

通过执行相似性和语义搜索,我们可以开始更有效地与数据交互。但我们还可以更进一步,并将一些无监督学习加入其中。这将帮助我们识别 WikiArt 数据集中的艺术模式,从风格到主题,甚至难以用语言表达的主题。

我们将通过两种方式做到这一点

  1. 降维:我们将使用 UMAP 将嵌入的维数降低到 2D,并在散点图中可视化数据。这将使我们能够看到图像根据其风格、类型和艺术家如何聚类。
  2. 聚类:我们将使用 K 均值聚类根据其嵌入对图像进行聚类,并查看出现了哪些组。

对于降维,我们将运行来自 FiftyOne Brain 的 compute_visualization(),并将之前计算的嵌入传入。我们指定 method="umap" 使用 UMAP 进行降维,但我们也可以使用 PCA 或 t-SNE

>>> fob.compute_visualization(dataset, embeddings="clip_embeddings", method="umap", brain_key="clip_vis")
Generating visualization...

现在,我们可以在 FiftyOne 应用中打开一个面板,在那里我们将看到数据集中的每个图像对应一个 2D 点。我们可以根据数据集中的任何字段(如艺术家或类型)对点进行着色,以查看这些属性在我们的图像特征中得到了多大的体现

UMAP Visualization

我们还可以对嵌入进行聚类,将相似的图像归类在一起——也许这些艺术作品的主要特征没有被现有的标签所捕捉,或者可能存在我们想要识别的不同的子类别。为了对我们的数据进行聚类,我们需要下载FiftyOne 聚类插件

!fiftyone plugins download https://github.com/jacobmarks/clustering-plugin

再次刷新应用程序后,我们就可以通过应用程序中的操作符访问聚类功能。按反引号键打开操作符列表,键入“cluster”,然后从下拉菜单中选择操作符。这将打开一个交互式面板,我们可以在其中指定聚类算法、超参数以及要聚类的字段。为了简单起见,我们将使用 $10$ 个聚类的 K-Means 聚类。

然后,我们可以在应用程序中可视化这些聚类,并查看图像如何根据它们的嵌入分组在一起。

K-means Clustering

我们可以看到,一些聚类选择了艺术家;另一些则选择了流派或风格。其他的更加抽象,可能代表了从数据中无法立即显现的子类别或其他分组。

识别最独特的艺术作品

我们可以问数据集一个有趣的问题:每张图片有多独特。这个问题对许多应用来说很重要,比如推荐相似的图片、检测重复图片或识别异常值。在艺术的背景下,绘画的独特性可能是决定其价值的重要因素。

虽然有无数种方法可以描述独特性,但我们的图像嵌入使我们能够根据每个样本与数据集中其他样本的相似程度,对每个样本进行定量的独特性评分。明确地说,FiftyOne Brain 的 compute_uniqueness() 函数会查看每个样本的嵌入与其最近邻居之间的距离,并根据此距离计算 0 到 1 之间的分数。分数为 0 表示该样本平淡无奇或与其他样本非常相似,而分数为 1 表示该样本非常独特。

>>> fob.compute_uniqueness(dataset, embeddings="clip_embeddings")  # compute uniqueness using CLIP embeddings
Computing uniqueness...
Uniqueness computation complete

然后,我们可以在嵌入面板中按此颜色,按独特性分数筛选,甚至按此排序,以查看数据集中最独特的图像。

most_unique_view = dataset.sort_by("uniqueness", reverse=True)
session.view = most_unique_view.view()  # Most unique images

Most Unique Images

least_unique_view = dataset.sort_by("uniqueness", reverse=False)
session.view = least_unique_view.view()  # Least unique images

Least Unique Images

更进一步,我们还可以回答哪个艺术家倾向于创作最独特的作品。我们可以计算每个艺术家所有作品的平均独特性分数。

>>> artist_unique_scores = {
...     artist: dataset.match(F("artist.label") == artist).mean("uniqueness") for artist in artists
... }

>>> sorted_artists = sorted(artist_unique_scores, key=artist_unique_scores.get, reverse=True)

>>> for artist in sorted_artists:
...     print(f"{artist}: {artist_unique_scores[artist]}")
Unknown Artist: 0.7932221632002723
boris-kustodiev: 0.7480731948424676
salvador-dali: 0.7368807620414014
raphael-kirchner: 0.7315448102204755
ilya-repin: 0.7204744626806383
marc-chagall: 0.7169373812321908
rembrandt: 0.715205220292227
martiros-saryan: 0.708560775790436
childe-hassam: 0.7018343391132756
edgar-degas: 0.699912746806587
albrecht-durer: 0.6969358680800216
john-singer-sargent: 0.6839955708720844
pablo-picasso: 0.6835137858302969
pyotr-konchalovsky: 0.6780653000855895
nicholas-roerich: 0.6676504687452387
ivan-aivazovsky: 0.6484361530090199
vincent-van-gogh: 0.6472004520699081
gustave-dore: 0.6307283287457358
pierre-auguste-renoir: 0.6271467146993583
paul-cezanne: 0.6251076007168186
eugene-boudin: 0.6103397516167454
camille-pissarro: 0.6046182609119615
claude-monet: 0.5998234558947573
ivan-shishkin: 0.589796389836674

看来,在我们数据集中作品最独特的艺术家是 Boris Kustodiev!让我们来看看他的一些作品。

kustodiev_view = dataset.match(F("artist.label") == "boris-kustodiev")
session.view = kustodiev_view.view()

Boris Kustodiev Artwork

用视觉品质描述艺术

最后,让我们回到基本原理,分析数据集中图像的一些核心品质。我们将计算每张图像的亮度、对比度和饱和度等标准指标,并查看这些指标如何与艺术品的艺术风格和流派相关联。

为了运行这些分析,我们需要下载FiftyOne 图像质量插件

!fiftyone plugins download https://github.com/jacobmarks/image-quality-issues/

刷新应用程序并再次打开操作符列表。这次键入 compute 并选择其中一个图像质量操作符。我们先从亮度开始。

Compute Brightness

当操作符运行完毕后,我们的数据集中将会有一个新字段,其中包含每张图像的亮度分数。然后,我们可以在应用程序中可视化这些数据。

Brightness

我们还可以按亮度颜色,甚至查看它如何与数据集中的其他字段(如风格)相关联。

Style by Brightness

现在对对比度和饱和度做同样的事情。以下是饱和度的结果。

Filter by Saturation

希望这说明了并非所有事情都归结为将深度神经网络应用于您的数据。有时,简单的指标可能同样具有信息量,并可以从不同的角度为您提供数据 🤓!

📚 对于大型数据集,您可能希望委托操作以供以后执行。

下一步是什么?

在本笔记本中,我们探索了如何使用多模态嵌入、无监督学习和传统的图像处理技术来分析图像中的艺术风格。我们已经了解了如何执行图像相似性和语义搜索、根据风格对图像进行聚类、分析图像的独特性以及计算图像质量指标。这些技术可以应用于各种各样的视觉数据集,从艺术收藏到医学图像再到卫星图像。尝试从 Hugging Face Hub 加载不同的数据集,看看你能发现什么见解!

如果您想更进一步,以下是一些您可以尝试的其他分析。

  • 零样本分类:使用来自 🤗 Transformers 的预训练视觉语言模型,根据主题或主题对数据集中的图像进行分类,而无需任何训练数据。查看此零样本分类教程以了解更多信息。
  • 图像字幕:使用来自 🤗 Transformers 的预训练视觉语言模型,为数据集中的图像生成字幕。然后,将其用于主题建模或根据这些字幕的嵌入对艺术作品进行聚类。查看 FiftyOne 的图像字幕插件以了解更多信息。

📚 资源

FiftyOne 开源项目

FiftyOne 是构建高质量数据集和计算机视觉模型的领先开源工具包。FiftyOne 已被全球的开发人员和研究人员下载了超过 200 万次,获得了他们的信赖。

💪 FiftyOne 团队欢迎来自开源社区的贡献!如果您有兴趣为 FiftyOne 贡献代码,请查看贡献指南

< > 在 GitHub 上更新