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 集成直接从 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 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 App,在样本网格中选中图像的复选框,然后单击照片图标以查看数据集中最相似的图像。在后端,单击此按钮会触发对相似性索引的查询,以查找与所选图像最相似的图像(基于预先计算的嵌入),并在 App 中显示它们。

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 App 中打开一个面板,我们将在其中看到数据集中每个图像的一个 2D 点。我们可以按数据集中的任何字段(例如艺术家或流派)为点着色,以查看我们的图像特征在多大程度上捕获了这些属性

UMAP Visualization

我们还可以在嵌入上运行聚类以将相似的图像分组在一起——也许这些艺术作品的主要特征没有被现有标签捕获,或者可能存在我们想要识别的独特子流派。为了聚类我们的数据,我们将需要下载 FiftyOne Clustering Plugin

!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 Image Quality Plugin

!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 的 Image Captioning Plugin 以获取更多信息。

📚 资源

FiftyOne 开源项目

FiftyOne 是构建高质量数据集和计算机视觉模型的领先开源工具包。凭借超过 200 万的下载量,FiftyOne 受到全球开发者和研究人员的信任。

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

< > 在 GitHub 上更新