Ahogrammer

Deep Dive Into NLP, ML and Cloud

MarkItDownでパワーポイントから画像を抽出

MarkItDownを使うと、ExcelやパワーポイントなどさまざまなファイルをMarkdown形式に変換できる。パワーポイントの場合、LLMを渡すことで画像のキャプションを生成できて便利なのだが、残念ながら生成時に並行処理を利用していないので、画像が多数含まれる場合に処理時間が長くなるという問題がある。そこで、画像だけを抽出してみたというのがこの記事の話。

結論

  • MarkItDownで変換する際にkeep_data_uris=Trueを指定する
  • 変換結果のMarkdownから正規表現Base64画像を抜き出す
  • 必要に応じてPillowで形式をPNGなどに変換する

準備

パッケージをインストールしておく。

pip install -q markitdown[pptx]

pptxの用意

デジタル庁の公開している「オープンデータ官民ラウンドテーブル」を例として使う。もちろん画像を含むpptxであれば他のものでも問題ない。以下に示すように、1ページ目から画像が含まれている。

画像の抽出

MarkItDownインスタンス化して、convertメソッドにkeep_data_uris=Trueを渡す。そうすると、変換結果のMarkdownBase64エンコードされた画像が埋め込まれる。

from markitdown import MarkItDown

filepath = "20210118_resources_data_round_table_05.pptx"
md = MarkItDown()
result = md.convert(filepath, keep_data_uris=True)
print(result.markdown)
<!-- Slide number: 1 -->

![](data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAA...)
# はじめてみよう!

地方版
オープンデータ官民ラウンドテーブル

【オープンデータ広報用キャラクター】
パッカーンくん
内閣官房 情報通信技術(IT)総合戦略室

![](data:image/png;base64,iVBORw0KGgoAAAAN...)
本書は、クリエイティブ・コモンズ 表示4.0 国際 (CC BY 4.0) にしたがって利用いただけます。
 (http://creativecommons.org/licenses/by/4.0/legalcode.ja)

あとは、正規表現を使ってMarkdownからエンコードされた画像の文字列を抽出すれば良い。このままLLMに渡してキャプションを生成してもいいが、LLMがサポートしていない画像形式の場合もあり得るので、以下ではPillowを使ってPNGに変換している。

import base64
import io
import re
from PIL import Image

# エンコードされた画像を抽出
pattern = re.compile(r"\!\[\]\(data:image/.+?;base64,(.+?)\)")
base64_str = pattern.search(result.markdown).group(1)
img_bytes = base64.b64decode(base64_str)

# PNGに変換
img = Image.open(io.BytesIO(img_bytes))
buffer = io.BytesIO()
img.save(buffer, format="PNG")
png_bytes = buffer.getvalue()

base64_str = base64.b64encode(png_bytes).decode("utf-8")
print(base64_str[:30])  # 先頭30文字だけ表示

元はJPEG形式だったが、PNGBase64エンコードした形式になっていることがわかる。

iVBORw0KGgoAAAANSUhEUgAAAOEAAA

これで、パワーポイント内の画像を取り出し、文字列として再利用できるようになった。あとは、LLMに投げる部分をasyncioを使って並行処理することで処理時間を短縮できる。ちなみに、Wordのファイルに対しても、同様の方法で画像を抽出できる。

参考資料