【CloudVisonAPI】シフト表からカレンダーに予定を入れる作業を自動化したい【Python】

## はじめに
使い物にはならなかったのですが、学びにはつながったので共有します。
主に、GoogleCloudVisonAPIに対する知見の共有となります。

## 目次
- #1 作ろうとしたアプリケーションについて
- #2 実装した機能
- #3 問題点（あきらめた理由）
- #4 開発環境
- #5 知見の共有
- #6 今後の修正案
- #7 最後に

## #1 作ろうとしたアプリケーションについて

1ヶ月のシフト表がカレンダー形式のPDFで共有されています。このカレンダーは1日毎に区切られていて、他の人のシフトも記載されているものです。

PDFだと自分のカレンダーに取り込むことができないので、画像認識を利用してテキストから自分のシフトを取得して、カレンダーへの追加まで自動化できないかと思いつき着手しました。

## #2 実装した機能

以下を実装しました。

- PDFをJPEGに変換するプログラム
    - Google Cloud Vision API は、直接ローカルに保存された PDF ファイルからテキストを抽出することはできないため
- JPEGをGoogleCloudVisonAPIに送信し、カレンダーをテキストに変換するプログラム
- 上記で取得したテキストから自分のシフトのみを取得し、リストにするプログラム

## #3 問題点（あきらめた理由）

もともとのPDFの画質が荒かった。
人の目であれば問題なく読めるが、一部の文字がつぶれていたり、薄くかすれてしまっている。

そのため、GoogleCloudVisonAPIでテキストに直したときに文字がうまく認識できなかったり、カレンダー形式の書き方のため、日付のみが並んでしまい、自分のシフトのみ取得することが困難だった。

## #4 開発環境

windows 10
Python 3.11.3
poppler 0.86.0 x86 (PDFからJPEGへの変換のために利用)

## #5 知見の共有
### PDFから画像への変換

pdf2imageライブラリを利用する。
内部で`poppler-utils`というツールを利用するため、[Poppler for Windows (alivate.com.au)](https://blog.alivate.com.au/poppler-windows/)からインストール。

設定については下記記事を参考にしました。
[PythonでPDFを画像に変換する（Windows10）](https://water2litter.net/rum/post/poppler_setup/index.html)

下記コードのように書くとPDFをJPEGに変換可能です。

```python
def convert_pdf_to_images(pdf_file_path, output_folder, output_format='jpeg', dpi):
    # PDFファイルを画像に変換
    images = convert_from_path(pdf_file_path, dpi=dpi)

    # 画像ファイルを保存
    image_file_paths = []
    for i, image in enumerate(images):
        image_file_path = f"{output_folder}/output_{i}.{output_format}"
        image.save(image_file_path, output_format.upper())
        image_file_paths.append(image_file_path)

    return image_file_paths
```

4つ目の引数のdpiで解像度を指定しています。デフォルトは200で、より大きい値を指定すれば実行時間と引き換えに解像度を高くできるようです。

### GoogleCloudVisonAPIの設定

以下の手順で行います。

ChatGPTに質問すればいい感じに説明してくれるので概要だけ述べておきます

1. Google Cloud Consoleにアクセス
2. プロジェクトの作成
3. Vision APIを有効にする
4. サービスアカウントの作成
5. サービスアカウントにロールを付与
    1. サービスアカウントのロールを設定する画面
    2. 「ロールを選択」をクリック
    3. 「Cloud Vision APIの管理者」を選択
6. キーの生成とダウンロード
    1. キーを生成する画面で、「キーの生成」ボタンをクリックし、キーの種類として「JSON」を選択
7. JSONファイルの配置
    1. アプリケーション用のフォルダのルートディレクトリ配置
8. 環境変数の設定
    1. Windows上で使用するので、環境変数の編集を行い、新規追加を選択し、`GOOGLE_APPLICATION_CREDENTIALS`という名前でJSONファイルまでのパスを指定します。

### GoogleCloudVisonAPIの利用例

```python
from google.cloud import vision
from google.cloud.vision_v1 import types
import io

def detect_text(image_path):
    client = vision_v1.ImageAnnotatorClient()

    # 画像を読み込む
    with io.open(image_path, 'rb') as image_file:
        content = image_file.read()

    image = types.Image(content=content)

    # 特徴量設定
    feature = types.Feature(
        type_=vision_v1.Feature.Type.TEXT_DETECTION,
    )

    # ImageAnnotatorClientに渡すリクエストを作成
    request = types.AnnotateImageRequest(
        image=image,
        features=[feature],
        image_context=types.ImageContext(language_hints=["ja"])
    )

    response = client.annotate_image(request=request)

    # 検出されたテキストを返す
    text = response.full_text_annotation.text
    return text
```

上記のようにコードを作成しました。

`AnnotateImageRequest`のオブジェクトを作成することで、特徴量設定や、言語をあらかじめ指定することができるようです。

[Cloud Vision のドキュメント  |  Cloud Vision API  |  Google Cloud](https://cloud.google.com/vision/docs?hl=ja)

## #6 今後の修正案

- 現在はローカル環境のPDFファイルを利用しているため、PDFをJPEGに変換しています。
    - Vision APIでPDFから直接テキストに変換するにはGCS(AWSでいうS3)の利用が不可欠なようなので避けていました。
- PDFから画像への変換でより良い方法を探す。
    - 現状、JPEGへの変換で解像度を高めに設定しても、画質が落ちてしまう。
    - pdf2image以外の方法で画質を保てるものを探す。

## #7 最後に

読んでいただきありがとうございました。

もし修正案などが思い当たる方がいましたら、何卒ご教授をお願い致します。