🚀

iiif-prezi3を使って、動画にアノテーションを付与する

2024/10/09に公開

概要

iiif-prezi3を使って、動画にアノテーションを付与する方法に関する備忘録です。

アノテーションの付与

Amazon Rekognitionのlabel detectionを用います。

https://docs.aws.amazon.com/rekognition/latest/dg/labels.html?pg=ln&sec=ft

以下などでサンプルコードが公開されています。

https://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/labels-detecting-labels-video.html

特に、GetLabelDetectionにおける集計をSEGMENTSにすることで、StartTimestampMillisEndTimestampMillisを得ることができます。

ただし、以下の点に注意が必要です。

SEGMENTS による集計の場合、境界ボックス付きの検出されたインスタンスに関する情報は返されません。

使用するデータ

『県政ニュース 第1巻』(県立長野図書館)を使用します。

https://www.ro-da.jp/shinshu-dcommons/library/02FT0102974177

マニフェストファイルへの反映

以下の記事などを参考に、マニフェストファイルが作成済みであるとします。

https://zenn.dev/nakamura196/articles/bf748ba5868e86

以下のようなスクリプトにより、マニフェストファイルにvttファイルを追加します。

from iiif_prezi3 import Manifest, AnnotationPage, Annotation, ResourceItem, config, HomepageItem, KeyValueString

#| export
class IiifClient:

    def load_manifest(self, manifest_path):
        with open(manifest_path, "r") as f:
            manifest_json = json.load(f)

        manifest = Manifest(**manifest_json)

        return manifest


    def add_label_segment(self, manifest_path):
        manifest = self.load_manifest(manifest_path)

        label_path = f"{self.input_dir}/output_label_seg.json"

        with open(label_path, "r") as f:
            label_seg = json.load(f)

        canvas = manifest.items[0]

        labels = label_seg["Labels"]

        anno_page_id = f"{canvas.id}/page1"

        anno_page = AnnotationPage(id=anno_page_id)

        canvas.annotations.append(anno_page)

        for i in range(len(labels)):
            label = labels[i]
            start = label["StartTimestamp"] / 1000
            end = label["EndTimestamp"] / 1000
            name = label["Label"]["Name"]

            anno_id = f"{anno_page_id}/a{i}"

            anno = Annotation(
                id=anno_id,
                motivation="tagging",
                target=canvas.id + "#t=" + str(start) + "," + str(end),
                body={
                    "type": "TextualBody",
                    "value": name,
                    "format": "text/plain",
                }
            )            

            anno_page.add_item(
                anno
            )

        output_path = f"{self.input_dir}/manifest_label_seg.json"

        with open(output_path, "w") as f:
            f.write(manifest.json(indent=2))

        return output_path
        

以下のようなマニフェストファイルが作成されます。

https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/manifest_label_seg.json

{
  "@context": "http://iiif.io/api/presentation/3/context.json",
  "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/manifest.json",
  "type": "Manifest",
  "label": {
    "ja": [
      "県政ニュース 第1巻"
    ]
  },
  "requiredStatement": {
    "label": {
      "ja": [
        "Attribution"
      ]
    },
    "value": {
      "ja": [
        "『県政ニュース 第1巻』(県立長野図書館)を改変"
      ]
    }
  },
  "homepage": [
    {
      "id": "https://www.ro-da.jp/shinshu-dcommons/library/02FT0102974177",
      "type": "Text",
      "label": {
        "ja": [
          "信州デジタルコモンズ 県立長野図書館所蔵資料"
        ]
      }
    },
    {
      "id": "https://jpsearch.go.jp/item/sdcommons_npl-02FT0102974177",
      "type": "Text",
      "label": {
        "ja": [
          "ジャパンサーチ"
        ]
      }
    }
  ],
  "items": [
    {
      "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas",
      "type": "Canvas",
      "height": 480,
      "width": 640,
      "duration": 619.61962,
      "items": [
        {
          "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas/page",
          "type": "AnnotationPage",
          "items": [
            {
              "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas/page/annotation",
              "type": "Annotation",
              "motivation": "painting",
              "body": {
                "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/video.mp4",
                "type": "Video",
                "height": 480,
                "width": 640,
                "duration": 619.61962,
                "format": "video/mp4"
              },
              "target": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas"
            }
          ]
        }
      ],
      "annotations": [
...
        {
          "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas/page1",
          "type": "AnnotationPage",
          "items": [
            {
              "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas/page1/a0",
              "type": "Annotation",
              "motivation": "tagging",
              "body": {
                "type": "TextualBody",
                "value": "Text",
                "format": "text/plain"
              },
              "target": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas#t=0.0,3.503"
            },
            {
              "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas/page1/a1",
              "type": "Annotation",
              "motivation": "tagging",
              "body": {
                "type": "TextualBody",
                "value": "Advertisement",
                "format": "text/plain"
              },
              "target": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas#t=8.008,9.009"
            },
...
            {
              "id": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas/page1/a1139",
              "type": "Annotation",
              "motivation": "tagging",
              "body": {
                "type": "TextualBody",
                "value": "Snow",
                "format": "text/plain"
              },
              "target": "https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/canvas#t=616.182,616.182"
            }
          ]
        }
      ]
    }
  ]
}

ビューアでの表示例

ビューアでの表示例は以下です。

https://d1u7hq8ziluwl9.cloudfront.net/mirador/index.html?manifest=https://d1u7hq8ziluwl9.cloudfront.net/sdcommons_npl-02FT0102974177/manifest_label_seg.json

東大デジタル人文学の「IIIF動画アノテーション」で公開されているソースコードを利用しています。

https://dh.l.u-tokyo.ac.jp/activity/iiif/video-annotation

参考

なお、Amazon RekognitionでのGetLabelDetectionにおける集計をTIMESTAMPにすることで、一部のアノテーションについては、BoundingBoxが得られます。

これを利用することで、以下のように、矩形とともにアノテーションを表示することができました。

まとめ

IIIFを用いた動画ファイルへのアノテーションの付与にあたり、参考になりましたら幸いです。

Discussion