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

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

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

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

Q&A

0回答

857閲覧

スキャンデータ(pdf)→画像化→ハフ関数で線の検出し、線を削除→ocrをかけて文字を読み取る。が上手くいかなくて困ってます

yohoho

総合スコア2

PDF

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

0グッド

0クリップ

投稿2021/12/20 00:27

編集2021/12/20 02:35

前提・実現したいこと

表題の通り、pythonにて次の手順を行うコードを書いていますが、⑤のハフ関数で下線の検出が上手くいきません。
・スキャンデータ(pdf)を画像化(JPEG)化する
・各ページごとに次の手順を行う
①pdfをJPEGとして保存
②画像を必要箇所だけ切り取る
③画像をグレースケールに変換
④(ハフ関数で検出しやすくするために)③を白黒反転
⑤線をハフ関数で検出
⑥検出した線を③から削除(白線に置き換える)
⑦⑥にocrをかけて文字を読み取る

どうかお助け下さい…よろしくお願いいたします…

発生している問題・エラーメッセージ

⑤で線がひとつも検出されない。
そのため、下記のエラーコードが出ます

for line in lines: TypeError: 'NoneType' object is not iterable

該当のソースコード

python

1# プログラム|ライブラリ設定 2import PyPDF2 3import pathlib 4import os 5 6from pdf2image import convert_from_path 7from PIL import Image 8import sys 9from pyocr import pyocr 10from pyocr import builders 11import cv2 12import numpy as np 13import pandas as pd 14 15file = './321121709540.pdf' 16scan = file.replace('.pdf','') 17 18# インストール済みのTesseractのパスを通す 19path_tesseract = r"C:\Users\AppData\Local\Programs\Tesseract-OCR" 20if path_tesseract not in os.environ["PATH"].split(os.pathsep): 21 os.environ["PATH"] += os.pathsep + path_tesseract 22 23# OCRエンジンの取得 24tools = pyocr.get_available_tools() 25#print(tools) 26tool = tools[0] 27 28# プログラム2|フォルダ内のPDFを全て取得 29curdir = os.getcwd() 30 31# プログラム4|分割したPDFを保管するためのフォルダ作成 32path = os.path.join(curdir, scan) 33if not os.path.isdir(path): 34 os.makedirs(path) 35 36pdf_path = file 37 38# PDF -> Image に変換(150dpi) 39pages = convert_from_path(str(pdf_path), 150) 40 41# 画像ファイルを1ページずつ保存 42for i, page in enumerate(pages): 43 44 image_path = os.path.join(path, f'{i}.jpeg') 45 print(image_path) 46 # JPEGで保存 47 page.save(str(image_path),"JPEG") 48 49 #画像を切り取る 50 imp_crop = Image.open(image_path).crop((700,200,1200,400)) 51 imp_crop.save(image_path) 52 53 #画像の線を消す 54 img00 = cv2.imread(image_path) 55 ##画像をグレースケールに変換 56 gray = cv2.cvtColor(img00, cv2.COLOR_BGR2GRAY) 57 #cv2.imwrite(image_path, gray) 58 59 ##画像を白黒反転する(下線を検出しやすくするため) 60 bw = cv2.bitwise_not(gray) 61 bw_image = os.path.join(path, f'{i}_bw.jpeg') 62 cv2.imwrite(bw_image, bw) 63 64 ##下線を検出 65 lines = cv2.HoughLinesP(bw, rho=1, theta=np.pi/180, threshold=200, minLineLength=400, maxLineGap=2) 66 print(lines) 67 68 ##線を消す(白線を引く) 69 for line in lines: 70 x1, y1, x2, y2 = line[0] 71 # 線を消す(白で線を引く) 72 no_lines_img = cv2.line(gray, (x1,y1), (x2,y2), (255,255,255), 3) 73 74 # 4.OCR実行 75 builder = builders.TextBuilder(tesseract_layout=6) 76 result = tool.image_to_string(no_lines_img, lang="eng", builder=builder) 77 78 print(result) 79

試したこと

下のコードのように
pdfをページごとに分割した後に画像化をすると上手くいくので、おそらくJPEG化あたりで何かを間違えているのがと思いますが、原因が分からず困っている状態です。

python

1# プログラム|ライブラリ設定 2import PyPDF2 3import pathlib 4import os 5 6from pdf2image import convert_from_path 7from PIL import Image 8import sys 9from pyocr import pyocr 10from pyocr import builders 11import cv2 12import numpy as np 13import pandas as pd 14 15file = './9510.pdf' 16scan = file.replace('.pdf','') 17 18# インストール済みのTesseractのパスを通す 19path_tesseract = r"C:\Users\AppData\Local\Programs\Tesseract-OCR" 20if path_tesseract not in os.environ["PATH"].split(os.pathsep): 21 os.environ["PATH"] += os.pathsep + path_tesseract 22 23# OCRエンジンの取得 24tools = pyocr.get_available_tools() 25#print(tools) 26tool = tools[0] 27 28# プログラム2|フォルダ内のPDFを全て取得 29curdir = os.getcwd() 30 31# プログラム4|分割したPDFを保管するためのフォルダ作成 32path = os.path.join(curdir, scan) 33if not os.path.isdir(path): 34 os.makedirs(path) 35 36# プログラム5|PDFを分割 37pdf = PyPDF2.PdfFileReader(file) 38for page in range(pdf.numPages): 39 print(page) 40 newpdf = PyPDF2.PdfFileWriter() 41 newpdf.addPage(pdf.getPage(page)) 42 43 # PDFをページごとに分割 44 pageNo = format(page, '0>3') 45 splitpdf = os.path.join(path, f'{pageNo}.pdf') 46 with open(splitpdf, 'wb') as f: 47 newpdf.write(f) 48 49 # 3.pdfからjpgへの変換 50 img = convert_from_path(splitpdf) 51 filename = splitpdf.replace(".pdf",".jpg") 52 #print(img) 53 for images in img: 54 images.save(filename) 55 56 57 filename0 = splitpdf.replace(".pdf","") 58 #画像を切り取る 59 imp_crop = Image.open(filename).crop((900,200,1600,400)) 60 imp_crop.save(filename) 61 62 #画像の下線を消す 63 img00 = cv2.imread(filename) 64 ##画像をグレースケールに変換 65 gray = cv2.cvtColor(img00, cv2.COLOR_BGR2GRAY) 66 #cv2.imwrite(filename0+"_gray.jpg", gray) 67 68 ##画像を白黒反転する(下線を検出しやすくするため) 69 gray2 = cv2.bitwise_not(gray) 70 #cv2.imwrite(filename0+"_blackandwhite.jpg", gray2) 71 72 ##下線を検出 73 lines = cv2.HoughLinesP(gray2, rho=1, theta=np.pi/180, threshold=200, minLineLength=400, maxLineGap=2) 74 print(lines) 75 76 ##線を消す(白線を引く) 77 for line in lines: 78 x1, y1, x2, y2 = line[0] 79 # 線を消す(白で線を引く) 80 no_lines_img = cv2.line(img00, (x1,y1), (x2,y2), (255,255,255), 3) 81 cv2.imwrite(filename0+"_noline.jpg", no_lines_img) 82 os.remove(filename) 83 84 # 3.原稿画像の読み込み 85 86 img_org = Image.open(filename0+"_noline.jpg") 87 88 # 4.OCR実行 89 builder = builders.TextBuilder(tesseract_layout=6) 90 result = tool.image_to_string(img_org, lang="eng", builder=builder) 91 92 print(result) 93

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

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

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

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

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

ppaul

2021/12/20 00:59

白紙で線一本だけのPDFを使っても同じエラーになりますか?
yohoho

2021/12/20 02:38

ご質問ありがとうございます。 白紙で線一本だけのpdfを使っても同じエラーになります。 「試したこと」に追記しました別の方法では、同じpdfを使っても線は検出されますので、 最初の下記手順の当たりで何かを間違えているのかもしれません。 ・スキャンデータ(pdf)を画像化(JPEG)化する ・各ページごとに次の手順を行う ①pdfをJPEGとして保存 お忙しいところ大変恐縮ですが、ご教示いただけますと幸いです…
ppaul

2021/12/20 04:31

・スキャンデータ(pdf)を画像化(JPEG)化する 成功しているか失敗しているかは、できたファイルを表示してみればわかるでしょう。
yohoho

2021/12/20 07:08 編集

ご返信ありがとうございます。 ・スキャンデータ(pdf)を画像化(JPEG)化する ここで画像化したファイルは、問題なく表示することができます。 また、①で分割後に保存したJPEGファイルも問題なく表示することができます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問