💨

pytesseract(OCR)で不要なスクリーンショットを判別した

2023/06/20に公開

macOS Venrura 13.3
Python3.9
tesseract 5.3.1
pytesseract 0.3.10

やりたいこと

以前、MacでWeb画面のスクリーンショットを自動で撮り続けたいという記事を書きました。順調にスクショを取り続けています。ただ、データが1日で1.5GBくらい増えてしまうので整理したいです。また、失敗している画像がけっこうあります。

  • 毎分取得していて、3ヶ月分くらいある。1日1440ファイルx90日くらい
  • 明らかに意図外の画面を別フォルダ移動させる(削除はマニュアル操作にする)
  • ある程度自動化したい

やったこと

インストール

tesseractのインストール方法。これはプラットフォームごとに違うので下記参考に。
https://tesseract-ocr.github.io/tessdoc/Installation.html

Macの場合

# 本体
brew install tesseract

# 日本語も読めるようにするにはこれを追加
brew install tesseract-lang
Ubuntuの場合

https://github.com/tesseract-ocr/tessdata/tree/main にあるjpn.traineddata
(40MBくらい)をダウンロードして、下記いずれかのtessdataのフォルダに入れます。

Various types of training data can be found on GitHub. Unpack and copy the .traineddata file into a ‘tessdata’ directory. The exact directory will depend both on the type of training data, and your Linux distribution.
Possibilities are:
/usr/share/tesseract-ocr/tessdata
/usr/share/tessdata
/usr/share/tesseract-ocr/4.00/tessdata.

Pythonのライブラリをインストール

pip install Pillow  # 画像の取得
pip install pytesseract  # OCR
pip install tqdm  # 進捗ゲージの表示

デモ

この画面で試してみます。左側に日本語のサインイン画面、右側に英語でElastiCacheの宣伝が入っています。

コード

OCRの部分

画像の中から読めた分をtextで返します。このコード単体で確認用に使えます。
custom_oem_psm_configでOCRの設定が変えられますが、書いてある設定値で固定になるかもしれません。

import pytesseract
from PIL import Image


def ocr_image(image_path):
    img = Image.open(image_path)

    custom_oem_psm_config = r"--oem 3 --psm 6 -l eng+jpn"

    text = pytesseract.image_to_string(img, config=custom_oem_psm_config)

    return text


image_path = "xxxx.png"

text = ocr_image(image_path)

print(text)

上の画像に対するOCR結果はこうなります。あまり正確とは言えませんが・・・。

aws
へ ー プ
IAM ユ ー ザ ー と し て サ イ ン イ ン
DATABASE
ア カ ウ ン ト D ⑫ 柘 ま た は ア カ ヵ ウ ン ト エ イ リ ,
7” Save today with
es Amazon ElastiCache
ュ ー ダ ー 鉄 け は
data tiering
ス ヮ ー ド Achieve 60%+ savings with
' Amazon ElastiCache data tiering
as compared to running
ロ こ の o ア カ ヵ ウ ン ト を 記 誌 す る at maximum utilization ③
on R6g nodes ve a Dyer
| サ イ シ ィ ン | [冒「 臺臺
ee
‘RBH 7911S Y— © 1996-2023, Amazon Web Services, Inc. or its affiliates.

文字を抽出して全部使うのには厳しいですが、今回の目的は判別だけなので、この画像にだけ出てくる文字をピックアップして、それが揃えば判別できるのでOKとします。

例えば、抽出したテキストに"記 誌 す る"が揃っていればこの画面だと判別できそうです(※場合による)。判定のコードは以下を使います。

OCRされた結果はスペースが入っていますが、text = text.replace(" ", "")などでスペースを消してから判定しています。keywordsの中に判定する複数の文字列を入れてもよいですが、今は1つだけにします。

keywords = ["記誌する"]
if all(key in text for key in keywords):
    # 揃った   

フォルダにあるPngを全部調べる

  • original_dirからdestination_dirに移動
  • keywordsが揃わなかったファイルをshutilで別フォルダに移動(あとで手動で消す想定)
  • tqdmで進捗確認
import glob
import os
import shutil

import pytesseract
from PIL import Image
from tqdm import tqdm


def ocr_image(image_path):
    img = Image.open(image_path)
    custom_oem_psm_config = r"--oem 3 --psm 6 -l eng+jpn"

    text = pytesseract.image_to_string(img, config=custom_oem_psm_config)

    return text


def move_file(image_file, destination_dir):
    # print("Move:", image_file)
    shutil.move(image_file, os.path.join(destination_dir, os.path.basename(image_file)))


original_dir = "/path/to/original/dir"
destination_dir = "/path/to/temp/dir"

keywords = ["記誌する"]

image_files = sorted(glob.glob(os.path.join(original_dir, "**", "*.png"), recursive=True))

# Loop over the files with a progress bar from tqdm
for image_file in tqdm(image_files, total=len(image_files), unit="file"):
    text = ocr_image(image_file)
    text = text.replace(" ", "")

    if all(key in text for key in keywords):
        move_file(image_file, destination_dir)    

まとめ

  • pytesseractを使って、OCRでスクリーンショットの判別をできるようになりました
  • 判定の基準をいろいろ試すのがちょっと大変かもしれません
  • 時間がかかるのが課題です。1ファイル4〜8秒かかります
  • 目視、手動でやったほうが早い場合もあるかも?

Discussion