電算倶楽部 富山県のコンピュータ社会人サークル

富山県、特に滑川市、富山市、魚津市周辺で活動している社会人サークルです。

スキャンしたPDFの処理を考える その3 検索の仕組みを考える

https://s-densan.hatenablog.com/entry/2021/02/11/ocr2の続きです。

処理のステップ

  • PDFを画像に変換する
  • 画像にOCR処理をかける
  • 検索の仕組みを考える ←今回はここ

ファイル検索について

Windowsのファイル検索では一部のファイルは内部のデータまで検索してくれます。 テキストファイルはわかりやすいですが、ExcelなどのオフィスファイルやJPG画像のメタ情報(タイトルやタグなど)も対象です。画像はなぜかJPGだけのようです。

まずは手動で検索できるか確認してみます。

JPG画像を右クリックし、「詳細」タブの「コメント」に、OCRされた文章を貼り付けます。

f:id:s-densan:20210215195245p:plain

その後、エクスプローラーで検索します、が初期状態では多分見つかりません。 下図のように「詳細オプション」から「ファイル コンテンツ」にチェックを入れると見つかります。

f:id:s-densan:20210215195457p:plain

大丈夫そうですね。

ところで今設定した「コメント」というのは、Exif情報のようです。 Exif情報は写真を撮った場合に画像に付与される情報で、例えばカメラの機種や焦点距離などの撮影時の情報などが含まれます。

必要コマンドのダウンロード

Exifを操作するツールであるexiftoolを使います。

exiftoolをインストールし、以下のコマンドを実行します。

exiftool (画像ファイル名)

以下のように画像情報が出力されれば成功です。 このファイルはコメントに日本語を設定してありました。

ExifTool Version Number         : 12.18
File Name                       : sa.jpg
Directory                       : .
File Size                       : 513 KiB
File Modification Date/Time     : 2021:02:15 19:51:04+09:00
File Access Date/Time           : 2021:02:15 19:51:04+09:00
File Creation Date/Time         : 2021:02:10 13:56:02+09:00
File Permissions                : rw-rw-rw-
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.00
Resolution Unit                 : inches
X Resolution                    : 300
Y Resolution                    : 300
Exif Byte Order                 : Big-endian (Motorola, MM)
XP Comment                      : 蝠・繧オ繝シ繝薙せ繝・じ繧、繝ウ諤晁・↓繧医k髢狗匱繧「繝励Ο繝シ繝√↓髢「縺吶k谺。縺ョ險倩ソー繧定ェュ繧薙〒,險ュ蝠・..4縺ォ遲斐∴繧医・...邱丞粋螳カ髮サ繝。繝シ繧ォ縺ョR遉セ縺ッ,窶懷▼蠎キ"繧偵ユ繝シ繝槭→縺励◆陬ス蜩√→縺励※,菴鍋オ・・險・豢サ蜍暮㍼..險・繝ゥ繝ウ繝九Φ繧ー繧ヲ繧ゥ繝・メ縺ェ縺ゥ縺ョ蛛・蠎キ讖溷勣繧定」ス騾,雋ゥ螢イ縺励※縺・k縲・...[譁ー 陬ス蜩√↓菫ゅk蜿也オ・...R遉セ縺ッ,莠コ縲・′驥崎ヲ悶☆繧倶セ。蛟、縺娯懊Δ繝寂昴°繧俄懊さ繝・縺ク縺ィ繧キ繝輔ヨ縺励※縺・k霑大ケエ縺ョ迥カ..豕√r雕上∪縺医※,閾ェ遉セ縺ョ陬ス蜩√r騾壹§縺滉ココ縲・・逕滓エサ縺ョ繝・ぅ繧ク繧ソ繝ォ蛹悶・蜿也オ・r謗ィ騾イ縺励※縺翫j,..繧ケ繝槭・繝医ヵ繧ゥ繝ウ逕ィ縺ョ繧「繝悶Μ繧ア繝シ繧キ繝ァ繝ウ繧ス繝輔ヨ繝峨ヨ繧ヲ繧ァ繧「(莉・荳九Μ繧コ繧ケ繝槭・繧「繝励Μ縺ィ縺・≧)繧・.髢狗匱縺励※縺・k縲ゅせ繝槭・繧「繝励Μ縺ョ蛻ゥ逕ィ閠・・,菴鍋オ・・險医〒貂ャ螳壹@縺滉ス馴㍾,菴楢р閧ェ邇・遲玖i..驥上↑縺ゥ縺ョ繝・・繧ソ繧偵せ繝槭・繝医ヵ繧ゥ繝ウ縺ォ霆「騾√@縺ヲ,貂ャ螳夂オ先棡縺ョ螻・豁エ繧帝夢隕ァ縺吶k縺薙→縺後〒縺・.繧九ゅ せ繝槭・繧「繝励Μ縺ッ,菴鍋オ・・險医・雉シ蜈・閠・・縺・■,蛟倶ココ諠・ア,雜」蜻ウ繝サ蝸懷・ス,蛛・蠎キ縺ォ髢「縺・.繧九い繝ウ繧ア繝シ繝 医↓蝗樒ュ斐@縺溯・↓蟇セ縺励※,辟。譁吶〒謠蝉セ帙@縺ヲ縺・k縲・...R遉セ縺ッ,菴鍋オ・・險医・譁ー陬ス蜩√r蜊雁ケエ蠕後↓逋コ螢イ 縺吶k縺薙→繧呈アコ螳壹@縺溘ゆスオ縺帙※,迴セ蝨ィ謠蝉セ・.縺励※縺・k繧ケ繝槭・繧「繝励Μ繧貞姐譁ー縺励※,譌・縲・・蛛・蠎キ縺ォ髢「繧上k豢サ蜍輔ョ繝シ繧ソ(莉・荳・蛛・蠎キ豢サ蜍・.繝ュ繧ー縺ィ縺・≧繧翫上r逋サ骭イ縺ァ縺阪k譁ー縺溘↑繧ケ繝槭・繧「繝悶Μ繝シ(莉・荳 ・蛛・蠎キ邂。逅・い繝励ヶ繝ェ縺ィ縺・≧)縺ォ縺・.繧九%縺ィ縺ォ縺励◆縲ょ▼蠎キ豢サ蜍輔Ο繧ー縺ォ縺ッ,菴鍋オ・・險医°繧牙叙蠕励☆繧 九ョ繝シ繧ソ縺ォ蜉縺医※,豢サ蜍暮㍼險・.縺ァ險域クャ縺吶k豁ゥ謨ー,閼域牛,逹。逵譎る俣縺ェ縺ゥ縺ョ豢サ蜍暮㍼,鬟滉コ句・螳ケ,驕句虚險倬鹸縺ェ縺ゥ縺悟性縺セ繧後k縲・.縺セ縺・蛛・蠎キ邂。逅・い繝励Μ縺ッ,縺薙l縺セ縺ァ縺ョ蛟倶ココ縺ォ髯仙ョ壹@縺溷茜逕ィ縺ォ蜉縺医※,蛻ゥ逕ィ閠・酔螢ォ縺ョ繧ウ..繝溘Η繝九ユ繧」豢サ蜍輔↓繧ょ茜逕ィ縺ァ縺阪k譁ケ驥昴↓縺励◆縲ょ・菴鍋噪縺ォ縺ッ,蛛・蠎キ邂。逅・い繝励Μ縺ョ蛻ゥ逕ィ閠・′..險倬鹸縺励◆蛛・蠎キ豢サ蜍募ヲゅげ繧偵う繝ウ繧ソ繝シ繝阪ャ繝井ク翫・繧ウ繝ュ繝溘Η繝九ユ繧」(莉・荳九が繝ウ繝ゥ繧、繝ウ繧ウ繝溘Η..繝九ユ繧」縺ィ縺・≧)縺ァC蜈ア譛峨§,縺贋コ偵>縺ョ險倬鹸縺ォ繧ウ繝。繝ウ繝医r莉倥¢縺溘r縺溘j繝ェ繧ェ繝ウ繝ゥ繧、繝ウ繧ウ繝 溘Η繝・.繝・ぅ蜀・〒鬆・ス阪r遶カ縺・粋縺」縺溘j,蟆る摩螳カ縺梧怏譁吶〒謖・ー弱@縺溘j縺ィ縺・▲縺・螟壽ァ倥↑譁ケ豕輔〒繧ウ..繝溘Η繝九ユ繧」豢サ蜍輔′縺ァ縺阪k縺斐%縺ィ繧堤岼謖・☆縺薙#縺薙→縺ォ縺倥◆縲・...R遉セ縺ッ,蛛・蠎キ邂。逅・・繝悶Μ縺ィ繧ェ繝ウ繝ゥ繧、繝ウ繧ウ繝溘Η繝九ユ繧」繧定檮蜷医§縺溘し繝シ繝薙せ(莉・荳・譁ー..繧オ繝シ繝薙せ縺ィ縺・≧縺・j繧呈エサ逕ィ縺倥〒繝薙ず繝阪せ繧呈僑螟ァ莠・k縺溘a縺ォ閾ェ遉セ縺ァ繧ェ繝ウ繝ゥ繧、繝ウ繧ウ繝溘Η繝・.繝・ぅ繧帝°蝟カ縺・谺。縺ォ遉コ縺咎未騾」驛ィ鄂イ縺ァ譁ー繧オ繝シ 繝薙せ縺ョ髢狗匱,驕句霧繧定。後≧縺薙→縺ォ縺励◆縲・...(1)蛛・蠎キ蠅鈴イ莠区・ュ驛ィ..蠕捺擂縺九i陦後▲縺ヲ縺・◆菴鍋オ・・險・ 豢サ蜍暮㍼險医r蜷ォ繧蛛・蠎キ讖溷勣縺ョ蝠・刀莨∫判,髢狗匱縺ォ蜉縺・...|繧ッ|
Padding                         : (Binary data 2096 bytes, use -b option to extract)
Comment                         : PFU ScanSnap Manager #S1500
About                           : uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b
Warning                         : [minor] Fixed incorrect URI for xmlns:MicrosoftPhoto
Image Width                     : 2103
Image Height                    : 3065
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 2103x3065
Megapixels                      : 6.4

日本語の部分は化けてしまいます。

また、以下のコマンドでコメントの設定ができます。

exiftool -XPComment='(設定する文字列)' (画像ファイル名)

ただし、日本語だとうまく設定できません。 そこでjsonファイルを作って、それを入力させます。

exifinfo.jsonという名前で以下のデータを含むテキストファイルを作成します。文字コードUTF-8としてください。

[{
  "XPComment": "日本語のテストです"
}]

画像ファイルと同じフォルダにexifinfo.jsonを保存し、以下のコマンドを実行します。

exiftool -g -json='exifinfo.json' (画像ファイル名)

1 image files updatedと表示されればOKです。 ファイルのプロパティを見ると反映されています。

f:id:s-densan:20210216203728p:plain

プログラムを作る

指定したフォルダの中のすべての画像に対してコメントを設定するプログラムです。

# ocr_card.py
import json
import tempfile
import os
from typing import List, Dict
import glob
import subprocess

def main():
    # 入力フォルダ
    image_dir = r'C:\ocr_src'

    # 入力フォルダ内のファイル一覧を取得
    image_file_list = glob.glob(os.path.join(image_dir, '*'))

    text_path_list = []
    for image_path in image_file_list:
        # 対象とする拡張子
        allow_exts = ['.jpg', '.jpeg', '.png', '.bmp', '.webp']
        if os.path.splitext(image_path)[1].lower() not in allow_exts:
            # 対象外のファイルの場合は次のファイルへ
            continue
        # 出力テキストファイルパス
        text_path = os.path.splitext(image_path)[0] + '.txt'
        # OCR実行
        ocr_result = set_exif(image_path, "ここにOCRした\n文字を設定します。")
        if ocr_result:
            text_path_list.append(text_path)
    print('完了')
    print('\n'.join(text_path_list))

def set_exif(image_path: str, comment: str) -> bool:
    """
    一つの画像ファイルに対し、exifコメント(XP Comment)を設定する。
    
    Parameters
    ----------
    image_path : str
        設定対象の画像ファイルパス
    comment : str
        XP Commentに設定する文字列
    
    Returns
    -------
    bool
        成否(true:成功, false:失敗)
    """
    # プログラム名(必要ならばフルパスで指定)
    program = 'exiftool'

    json_data = [ {'XPComment': comment} ]

    # 入力画像ファイルが存在しない場合は終了
    if not os.path.isfile(image_path):
        return False

    with tempfile.TemporaryDirectory() as dname:
        json_path = os.path.join(dname, 'tmp.json')
        with open(json_path, 'w') as fp:

            fp.write(json.dumps(json_data))

            # 実行するコマンド
            command = f'{program} -json="{fp.name}" "{image_path}"'

            # コマンド実行
            try:
                print(command)
                res = subprocess.check_output(command)
            except Exception as ex:
                print(f'コマンド実行中にエラーが発生しました。command = {command}, Exception = {ex}')
                return False
            return True

終わりに

画像にコメントを設定することができました。 応用すればコメントではなくタグやタイトルなど他の項目も設定できるかと思います。 ドキュメントの整理だけでなく写真の整理でも役立ちそうです。