質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Tesseract

Tesseractは、Googleが提供しているオープンソースのOCRエンジンです。機械学習があり60以上の言語に対応でき、日本語の文字認識も可能です。さらに精度を上げることもできます。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

329閲覧

Google Colabo上でのPythonの処理で、PDFから日本語を読み取って文字列として出力する際に、出力される文字列が文字化け状態みたいな形になってしまう

shinro

総合スコア13

Tesseract

Tesseractは、Googleが提供しているオープンソースのOCRエンジンです。機械学習があり60以上の言語に対応でき、日本語の文字認識も可能です。さらに精度を上げることもできます。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2024/03/14 13:18

編集2024/03/14 15:25

実現したいこと

特定のPDFから日本語を読み取り、文字列として出力をしたいのですが、なぜか文字化けしたような文字列が出力されてしまうのでそれを直したいです。
他のPDFではある程度文字を出力できたため、特定のPDFのデータ構造についての問題なのかな? と思っているのですが、具体的に何が課題なのか分からないという状態です。

発生している問題・分からないこと

以下のコードを実行すると、文字化けしたような意味不明な文字列が出力されます。
二値化、モルフォロジー変換をした後の画像を確認したりしましたが、該当の画像について、人間の目には解像度は悪くなくOCRできそうだと感じました。

エラーメッセージ

error

1エラーではないです。

該当のソースコード

!pip install pypdf !pip install pillow !apt-get install -y tesseract-ocr !apt-get install tesseract-ocr-jpn !apt-get install -y libtesseract-dev !pip install pytesseract !pip install opencv-python-headless import io import os from pypdf import PdfReader os.environ['TESSDATA_PREFIX'] = '/usr/share/tesseract-ocr/4.00/tessdata' from PIL import Image import pytesseract import cv2 import numpy as np def preprocess_image(image): """画像の前処理を行う関数""" img_array = np.array(image).astype(np.uint8) # 画像のチャンネル数を確認 if len(img_array.shape) == 2: # グレースケール画像の場合、そのまま使用 gray = img_array elif img_array.shape[2] == 3: # RGBカラー画像の場合、グレースケールに変換 gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY) else: raise ValueError("Unsupported image format") # 二値化 _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # モルフォロジー変換(ノイズ除去) kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=1) return Image.fromarray(opening) def extract_images_from_pdf(pdf_file): """PDFファイルから画像を抽出する関数""" reader = PdfReader(io.BytesIO(pdf_file)) images = [] for page in reader.pages: if '/XObject' in page['/Resources']: xObject = page['/Resources']['/XObject'] for obj in xObject: if xObject[obj]['/Subtype'] == '/Image': image_data = xObject[obj].get_data() images.append(image_data) return images def extract_text_from_image(image): """画像からテキストを抽出する関数""" text = pytesseract.image_to_string(image, lang='jpn', config='--psm 6') return text def process_pdf(pdf_file): """PDFを処理し、テキストデータを出力する関数""" images = extract_images_from_pdf(pdf_file) for i, img_data in enumerate(images): img = Image.open(io.BytesIO(img_data)) preprocessed_img = preprocess_image(img) text = extract_text_from_image(preprocessed_img) print(f"Image {i+1}:") print(text) print("-" * 50) # Google Colabでファイルをアップロードするためのコード from google.colab import files uploaded = files.upload() # アップロードされたPDFファイルを処理 for pdf_name, pdf_file in uploaded.items(): print(f"Processing {pdf_name}:") process_pdf(pdf_file) print("=" * 50)

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

1.最初は二値化、モルフォロジー変換は実施していませんでしたが、その段階で文字化けがひどかったので、データを見やすくする意図(元のデータに点線などが入っていて、その点線が、補足で書くような「1」として表れているのかなと思って、点線を消そうとしていました)でその2つの処理を追加しました。ただ、あまり改善した感じはしませんでした。
2.tesseract OCRに問題があるのかなと思い、EasyOCRでも試しましたが、同様に意味不明な文字列が出力されました。
tesseractOCRでは文字化けのような文字列が出てきて、EasyOCRでは漢字の羅列のようなデータが出てきました。

補足

<二値化等する前>
イメージ説明
1 1 I ! 1 1 I ! 1 I 1 1 ! 1 1 1 1 1 ! 1

IGT ien 0 iR 0 iR ii io io iiューューコー ーーュー ーー 」ュの 選吐

iA inO ioo ion io5 ioo ioっ iR nino 0 の jo5 iR jnm5 jiら0 joo joo 」R jm5b の 5 半 志

1 | | | 1 | | | | | 1 1 | 1 | | 1 1 | 1 ごmm

ーー Ne ッ>て Ne

の 加 ら ご

NO四 品ら

ーー

<二値化した後のterrasect>
イメージ説明
に| cn 3 まこ ここ プロ とっ つい とっ 「プい いつ いこ) っ 1 ーー ーー ーー ーー ーー トー つ
Fn HH やSs ピコ 間 il
ー し
記 し し 立 秦 へ 名 和司ら
ーm ーー KT の てン 月 " 3
ET に h 性
し に電還 ーー コ
半 邊了生に 病人時 s に al 間還|関人際 財
| ー ヽー マミ
ロ ヽー ヽー ロ
国 全国全あつ | ョh m 三 ミミ< 半 に |
ii ー
| rl Nerd RT ー
ここ 間 マー 本 に 半 二話ー征只そ S
し ごーー さきニーささーー ーー 一叶 3 中
ここ てm でつら …、 の1 こり | トー こョ| ホバーででーーの> にコ ご> ーー ーー ーー ーー ーー ーー く
AI Qp のP G理王理CO の の邊G ちよ やごOら ら ーー で
己 を 性 ジォニ 用 性 性 ごコル選ォニ ニニ ごテル包 避 ei二 用 避
トー ュン トー ニン ーー ーー ーー ーー にだ トー トコ の

<EasyOCR版>
イメージ説明
留 留 記 品 8 齢 岩 迫 台 呼 だ 窓 呂 る る さ 号 器 ワ ‥ こ 熟 = 曇 豊 ロ 1 糞 ~ こ @ 順 避 苗 @ ~ 邑 智 喜 喜 育 震 = 三 可 = 号 喜 可 言 宮 言 言 言 言 三 ! 宮 ‥ こ 美 三 | | こ 三 三 三 ごオ早さニ こ ごォ| | 巴 こ 三 | の ; ド 呂 る 器 呂 置 宮 呂 呂 呂 呂 呂 口 る ♪ 古 。 沓 。 宮 昌 昌 昌 昌 昌 昌 ・ ゆ ・ ・ 呂 | | 宮 呂 る 書 一 留 窓 8 会 留 っ 留 ~ + = 窓 口 窓 呂 留 会 呂 亘 号 ジ ヒ 一 ; ; 留 8 | 呂 会 』 @ 高 9 器 器 。 弓 | 8 ・ 留 る 慧 器 昌 宮 昌 器 宮 | ゆ 台 の 一 呂 留 る 豆 器 さ 器 器 三 可 の 皆 望 る 曾 島 器 ら 露 器 宮 曽 る 曾 三 曽 三 三 弓 ・ 上 曽 言 喜 昌 言 ね 器 8 留 じ 器 呂 1 一 呂呂留 8 る呂 こ 呂 留 吾令 口さ 三可器宮弓留っ命 じ る 中口 言こ呂呂るら三呂 8 9 留 呂呂呂 露 品 中 命 ・ ぶ 一 6 ゆ る ・ と ゆ 中 中 ゆ口口 口ロ ・ @ 語も論邑 ロ・ ざ 巾 一 命 八・ 間 口 ゆ ゆ ・ ・ 舘 ‥? ‥? ‥? さ さ? 。? さ? 埼? 。? 。? 3? ば 台 。? 。? ハ? 3 高 _己 さ? さ ‥ 。? 点ば 。? さ? ‥ ‥? さ? さ? ゅ さ 一 一 き ゆ さ や 昂 昌 ブ 8 昌 曽 ‥ ミ ど 8 器 器 こ 令 曾 留 言 留 昌 昌 昌 昌 昌 昌 昌 昌 昌 昌 き 昌 昌 昌 昌 昌 昌 昌 昌 雪 中 さ ご さ さ さ ; ♪ ♪ 家 畠 言 品 留 器 る 呂 町 ♪ 呂 言 奇 ぐ 昌 器 愚 窓 重 昌 ミ 邑 留 齢 台 昌 ハり 呂 土 留 会 号 留 じ 呂 ツ 呂 畠 昌 舎 さ の の ♪ 呂 高 器 8 邑 邑 呂 言 言 舎 皆 高 器 舘 る 昌 留 曽 器 る る 昌 呂 宮 昌 舎 言 号 島 呂 呂 言 骨 器 呂 弓 称 ツ 量 呂治 るズこ こ ご留呂 ゆ 留呂留言呂っっ言吾留ミ鉛 太 中 台石司 口守 言三言言るるミミ言言言言ミ言 び る ・ 命 ]」

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikedas

2024/03/14 13:29

「文字化け状態みたい」の具体例を示してください。実際の表示のスクリーンショットをとるなどして、質問文をを編集して追加してください。
shinro

2024/03/14 13:44

コメントありがとうございます、補足に文字化けの文字列を入れました。スクリーンショットの方がよければ取り直すことも可能です。 また、二値化等の意図として、最初の段階で出てきていた「1」といった表示が、元のPDFにあった点線に起因しているものかもしれないと思って、それを消すために二値化した側面がありました。
ikedas

2024/03/14 14:09

文字化けって、 正常に文字が表示されていない状況なんで、コピペして文字として写してもらうより、スクショを撮って画像として載せてもらったほうが状況がわかりやすいです。お手数おかけして申し訳ないですが。
shinro

2024/03/14 15:26

コメントありがとうございます、スクショを登録しました。
ikedas

2024/03/14 23:38

PDFに入っている画像をOCRでテキスト化するということですね。 であればPDFかどうかは本質ではないですよね。 その画像にノイズが乗っているといった原因でテキストを誤検出と考えられるので、画像を表示してみて内容を確かめてはどうですか。
winterboum

2024/03/15 00:02

OCR なツール名があるので私も「PDFを画像→ 紙にだしてOCRで読む」かと思っていたのですが、ソースのコメントに「"""PDFを処理し、テキストデータを出力する関数"""」とあるので、 ・PDFを処理してページイメージを作り、そのimg情報をOCRに読ませる。 ・PDFにテキスト情報があったら、イメージ経由せずに読み取る 様な・・・・ もし 「PDFにテキスト情報があったら、イメージ経由せずに読み取る」だとPDFに使われている文字コードを確認してみるべきか、と。 質問者さん 「PDFにテキスト情報があったら、イメージ経由せずに読み取る」 ですか?
can110

2024/03/15 01:43

以下PDFにて、colab上で提示コードを実行しましたが、おおむね正しく処理できました。 https://www.sumo.or.jp/pdf/kyokai/zaimu/h28_kessan.pdf 前処理前後の画像(.png)をsaveして提示すると回答得られやすくなると思います。
shinro

2024/03/15 11:54

>ikedasさん ありがとうございます、前処理後の画像は確認してみたことがあるのですが、ノイズが載っていたり等はなく、割と見やすく読み取りたい文字が白黒で浮かび上がっていました。
shinro

2024/03/15 12:16

>winterboumさん ありがとうございます、たしかに文字コードを確認する必要はあるかもしれませんね……。 「PDFにテキスト情報があったら、イメージ経由せずに読み取る」という意図はあまりしていないのですが、関数の細かい仕様まで把握しているわけではないので、もしテキスト情報があった場合そのような処理をすることになっているならありえますよね……。 その場合は、PDFの中にあるテキスト情報がそのまま出力されている、と考えればよいのでしょうか?
shinro

2024/03/15 12:18 編集

>can110さん ありがとうございます、二値化・ノイズ除去をした後の実際の画像をここに貼り付けてみるという感じでしょうか?
winterboum

2024/03/15 13:25

def process_pdf(pdf_file): """PDFを処理し、テキストデータを出力する関数""" の働きを読み込んでみることと、それが呼ばれているかどうかみるのでわかるでしょう。
shinro

2024/03/15 23:29

申し訳ないです! 「働きを読み込んでみる」というのと「呼ばれているかどうかみる」というのは具体的にどういうことでしょうか……?
ikedas

2024/03/16 00:55

実際の画像 (できれば二値化・ノイズ除去をする前と後の両方) を質問文を編集して貼り付けてほしいです。
winterboum

2024/03/16 08:39

働きを読み込んでみる は プログラムを読み込んで、その部分で何が行われているのかを理解する、ということです 何をする:OCRではなくtextをよみだしているのか否か 呼ばれているかどうかみる は色々ありますが、例えばdebug用のメッセージ出力をそこに入れて、呼ばれたら なんか出力される様にして 試す
ikedas

2024/03/16 11:15

コードを素直に読めば、extract_images_from_pdf()でPDFから画像を抽出し、抽出したそれらの画像をextract_text_from_image()でOCR処理してテキストを認識させているのだと読み取れます。 「文字化け状態みたい」という表現があるのでテキストエンコーディングの問題を疑っているのかもしれませんが、そうではないと思いますよ。
shinro

2024/03/16 23:38

皆様ありがとうございます、色々とこの操作についての知見が足りていないことを痛感しました……。 確実に自動化したいという作業だったわけでもないので、いただいた意見を参考に全体的に学びなおして(回答で書いていただいた内容はそもそも意識にすらなかったことも多かったので……)また自身で見直してみます、ありがとうございました!
guest

回答1

0

ベストアンサー

回答ではないのですが、


xObject = page['/Resources']['/XObject'] for obj in xObject: if xObject[obj]['/Subtype'] == '/Image': image_data = xObject[obj].get_data()

ここで、Imageサブタイプを持つオブジェクトのバイナリデータを取得してそのまま画像データとして使っているようですが、この方法で常に画像情報が正しく取得できるのかどうか疑問です。画像データはさまざまなフォーマット (JPEG、TIFF、ファックス、PNG等) で格納されていますし、圧縮されている場合もありますし、カラースペースやアルファチャネルの情報もあります。

調べてみるとpypdfのPageObject (ご質問のコードではpage変数がこのクラスのインスタンスです) にはimagesというプロパティがあり、ページ内の全ての画像についての情報のリストを返します。画像情報は辞書で、imageというキーの値は上でのべたようなことを考慮してなるべく正確に画像を変換したPILオブジェクトになっています。今回の質問が解決されるかどうかはわかりませんが、こちらを使ったほうがいいかもしれません。

投稿2024/03/16 12:00

編集2024/03/16 12:01
ikedas

総合スコア4337

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shinro

2024/03/16 23:39

解決したというわけではないのですが、大変参考になったのでベストアンサーにしていったんこのQAを閉じようと思います、ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問