メトロポリタン美術館のパブリック・ドメイン絵画画像をPythonで収集する

#はじめに
機械学習その他の用途で画像を収集し、さらに加工などを施し**公開したい場合**に、著作権が心配になる場合があります。

そこで著作権が切れている「**パブリック・ドメイン（PD）**」（最近では**Creative Commons Zero, CC0**の呼称もあります）で、ある程度の情報が整っている画像データセットとして、世界中の美術館が公開している美術品画像が存在します。

日本語で詳しく紹介している記事があまりなかったので、一例としてメトロポリタン美術館のパブリック・ドメイン画像データをPythonを使って自動取得する方法を記事にします。この記事ではPythonを使っていますが他言語でも簡単に取得可能です。

# メトロポリタン美術館コレクションのPD画像
## 概要
[メトロポリタン美術館](https://www.metmuseum.org/)とは、アメリカ・ニューヨークのマンハッタンのど真ん中にある、150年の歴史を持つ美術館です。世界中の古代から近現代の美術品を収蔵しており、美術館としては世界で4番目の来客数および床面積があります。アメリカ国内では最大です（**なんと私立！**）。

このメトロポリタン美術館は「[Open Access](https://www.metmuseum.org/about-the-met/policies-and-documents/open-access)」というプロジェクトとして、デジタル化された美術品写真をインターネットで無料公開しており、さらにCC0表記≒パブリック・ドメインの作品を明示しています。2020年12月時点で、**公称で406,000枚のパブリック・ドメイン画像が公開されている**そうです[^1]。

メトロポリタン美術館のウェブサイトに行き、[Search the Collectionのページ](https://www.metmuseum.org/art/collection/search)で"_Open Access_"にチェックを入れることで、以下のようにパブリック・ドメインの画像となっている美術作品を絞り込んで閲覧することができます。
![met_thum1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/928728/5c6497b9-6a3b-edb6-c716-9664960f0c6f.jpeg)
[^1]: 「なんでこんなに価値のある資産を無料公開して配ってるの？」と疑問に思われるかもしれません。欧米では「美術館は公共性を持ち、その人類の叡智である芸術作品をより広く多くの文化や教育の発展に寄与するべきだ！」のような理念があったりして、積極的に人々が芸術作品に触れることを奨励したりします。またMETは、昨今の機械学習の流れで活用されることも期待しているようです。

これはウェブサイト上で検索した結果ですが、コードで自動取得し画像のダウンロードまで行う手順を以下で紹介していきます。
（以下、メトロポリタン美術館をMETと表記します）

## 利用方法
MET公式サイト：[Open Access at The Met](https://www.metmuseum.org/about-the-met/policies-and-documents/open-access)
MET公式のGitHub：https://github.com/metmuseum/openaccess

METからパブリック・ドメインの画像を自動でダウンロードするには、以下の手順で行う必要があります。

1. GitHubから美術品データCSVをクローン
1. 美術品データCSVから、パブリック・ドメインの作品画像を特定
1. パブリック・ドメインの作品画像の「オブジェクト番号」を取得
1. 「オブジェクト番号」をMET Web APIにGETリクエストし、画像URLを得る

### 1. GitHubから美術品データCSVをクローン
大きなCSVをクローンするため、Git LFSを利用します。※git lfsがインストールされていない場合は、インストールすること。

```
git lfs clone https://github.com/metmuseum/openaccess.git
```

git lfs cloneが完了すると、`./openaccess`ディレクトリ配下に292MBのCSVファイルがダウンロードされます。

### 2. 美術品データCSVから、パブリック・ドメインの作品画像を特定
CSVデータをPandasで読み込みます。

```python:CSV読込

import pandas as pd

df_met = pd.read_csv('./openaccess/MetObjects.csv')
print(len(df_met))
# 474526
```


このCSVファイルには54個のカラムがありますが、欠損や細かな情報も多いです。主要なカラムの説明をします。

| カラム名 | 意味内容 |
|:--|:--|
|Object Number|作品番号（METの分類）|
|Is Public Domain|パブリックドメイン（著作権フリー）か|
|Object ID|デジタル上の作品番号（APIのリクエストに必要）|
|Object Name|美術品のジャンル|
|Title|作品名|
|Artist Display Name|作者名|
|Link Resource|掲載ウェブページURL|

ここで注意が必要なのは、`Link Resource`（掲載ウェブページURL）のカラムのURLに自動アクセスしても、METはロボットアクセスを禁止しているので画像URLは取得できません。つまり自動で画像をダウンロードしていくためには、画像のURLを取得する必要があります。

ここからパブリック・ドメイン画像を持つ作品のみを取得するには、`Is Public Domain`カラムで絞り込みます。

```python:パブリック・ドメインの絞り込み
df_met_pd = df_met[df_met['Is Public Domain']==True]
print(len(df_met_pd))
# 239371
```

あれ？リストにはパブリック・ドメイン画像が24万弱しかない？40万のパブリック・ドメイン画像を公開しているのでは？と疑問に思いましたが、リスト化されていないものがあるのでしょうかね。詳しく追及をせずに次に進みます。

パブリック・ドメイン画像と言っても、作品ジャンルがバラバラです。作品ジャンル（`Object Name`カラム）を集計すると、以下のような数量になっていることがわかります。

```python:作品ジャンルカウント
df_met_pd['Object Name'].value_counts().head(10)
```
```:結果
Print                                   36341
Drawing                                 14514
Photograph                               9089
Kylix fragment                           8886
Fragment                                 8128
Piece                                    6426
Painting                                 3047
Bowl                                     2842
…
```

例えばここから、絵画作品（`Painting`）のみに絞り込んで使ってみることにします。

```python:絵画作品に絞り込み
df_met_pd_paint = df_met_pd[df_met_pd['Object Name']=='Painting']
print(len(df_met_pd_paint))
# 3047
```

メトロポリタン美術館がデジタルデータで公開しているパブリック・ドメインの絵画作品は、リストでは3,047個であることがわかりました。

### 3. PD画像の「オブジェクト番号」を取得

画像URLを取得する前に、CSVの5カラム目`Object ID`（オブジェクトID）を取得する必要があります。例えば、先ほど絞ったパブリック・ドメインの絵画から、ランダムに1つ選んでオブジェクトIDを取得してみます。

```python:オブジェクトID取得
obj_id = df_met_pd_paint['Object ID'].sample(1).iloc[-1]
print(obj_id)
# 10524
```

### 4. MET Web APIから画像URLを得る
画像URLを得るには、登録不要のMET Web APIを利用します。METのWeb APIの仕様は以下で公開されており、API Key等も不要で利用可能です。
[The Metropolitan Museum of Art Collection API](https://metmuseum.github.io/)
注意として、
>「1秒間に80リクエストまでに制限してください（Please limit request rate to 80 requests per second）」

とのことです。

レスポンスはJSON形式で返ってきますので、Pythonの辞書に格納した上で表示してみましょう。

```python:WebAPIにGETリクエスト

import requests
import json

MET_API = 'https://collectionapi.metmuseum.org/public/collection/v1/objects/'
target_url = MET_API + str(obj_id)
res = requests.get(target_url)
res_dict = json.loads(res.text)
print(res_dict)
```

```:レスポンス結果
{'objectID': 10524,
 'isHighlight': False,
 'accessionNumber': '49.13',
 'accessionYear': '1949',
 'isPublicDomain': True,
 'primaryImage': 'https://images.metmuseum.org/CRDImages/ad/original/DT2032.jpg',
 'primaryImageSmall': 'https://images.metmuseum.org/CRDImages/ad/web-large/DT2032.jpg',
 'additionalImages': [],
…
```

見てわかる通り、このレスポンスのキー`'primaryImage'`と`'primaryImageSmall'`に格納された値が、画像URLです。小さい方の画像を表示してみます。

```python:JupyterNotebook上に画像表示
from IPython.display import Image
Image(res_dict['primaryImageSmall'])
```
<img width="300" alt="DT2032.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/928728/27b4d433-5924-c5e0-b1c1-90e206b203f7.jpeg">
無事、パブリック・ドメインの画像URLから画像が取得できました。

# おわりに
上記手順を（リクエスト回数に気を付けながら）自動化することで、パブリック・ドメインの美術作品画像を大量に自動的に取得できます。ウェブクローリングで細かなスクレイピング仕様に悩まされるよりも確実に、かつ作者や年代、ジャンルなどの情報が揃ったパブリック・ドメイン画像を収集することができます。

いくつかの美術館が公開しているパブリック・ドメインのデータセットやAPIを調べましたが、無料・登録不要の中ではメトロポリタン美術館のものが最も扱いやすいです。他にも「[シカゴ美術館](https://www.artic.edu/)」という超大型美術館がパブリック・ドメイン＋[APIで自動画像収集が可能](https://api.artic.edu/)ですが、こちらは大変複雑な仕様になっており、「**手軽に自動取得はさせないぞ！**」みたいな気合を感じます。いずれQiitaにシカゴ美術館のPDデータ取得方法も記事で書こうかなと思ってます。