前提・実現したいこと
表題の通り、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
白紙で線一本だけのPDFを使っても同じエラーになりますか?
ご質問ありがとうございます。
白紙で線一本だけのpdfを使っても同じエラーになります。
「試したこと」に追記しました別の方法では、同じpdfを使っても線は検出されますので、
最初の下記手順の当たりで何かを間違えているのかもしれません。
・スキャンデータ(pdf)を画像化(JPEG)化する
・各ページごとに次の手順を行う
①pdfをJPEGとして保存
お忙しいところ大変恐縮ですが、ご教示いただけますと幸いです…
・スキャンデータ(pdf)を画像化(JPEG)化する
成功しているか失敗しているかは、できたファイルを表示してみればわかるでしょう。
ご返信ありがとうございます。
・スキャンデータ(pdf)を画像化(JPEG)化する
ここで画像化したファイルは、問題なく表示することができます。
また、①で分割後に保存したJPEGファイルも問題なく表示することができます。
あなたの回答
tips
プレビュー