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

我们将首先从 🤗 Hub 将 WikiArt 数据集加载到 FiftyOne 中。这个数据集也可以通过 Hugging Face 的 datasets 库加载,但我们将使用 FiftyOne 的 🤗 Hub 集成直接从数据集服务器获取数据。为了加快计算速度,我们只下载前 $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 App 中可视化数据集

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 Brain 中的 compute_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 App 中的搜索图标并输入文本查询。

Semantic Search

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

💡 为了对大型数据集进行高效的向量搜索和索引,FiftyOne 原生集成了开源向量数据库

通过聚类和可视化揭示艺术主题

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

我们将通过两种方式实现这一点:

  1. 降维:我们将使用 UMAP 将嵌入的维度降低到 2D,并在散点图中可视化数据。这将使我们能够根据图像的风格、流派和艺术家查看它们的聚类方式。
  2. 聚类:我们将使用 K-Means 聚类根据嵌入对图像进行聚类,并查看出现哪些组。

对于降维,我们将运行 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”并从下拉菜单中选择操作符。这将打开一个交互式面板,我们可以在其中指定聚类算法、超参数以及要聚类的字段。为简单起见,我们将使用 K-Means 聚类,包含 $10$ 个簇。

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

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

看来,我们数据集中作品最独特的艺术家是鲍里斯·库斯托季耶夫!让我们看看他的一些作品。

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 上更新