1648833540
Heutzutage haben mittlere und große Unternehmen riesige Mengen an gedruckten Dokumenten im täglichen Gebrauch. Darunter sind Rechnungen, Quittungen, Unternehmensdokumente, Berichte und Medienmitteilungen.
Für diese Unternehmen kann der Einsatz eines OCR-Scanners viel Zeit sparen und gleichzeitig die Effizienz sowie die Genauigkeit verbessern.
Mithilfe von Algorithmen zur optischen Zeichenerkennung (OCR) können Computer gedruckte oder handgeschriebene Dokumente automatisch analysieren und Textdaten in bearbeitbaren Formaten aufbereiten, damit Computer sie effizient verarbeiten können. OCR-Systeme wandeln ein zweidimensionales Textbild, das maschinengedruckten oder handgeschriebenen Text enthalten könnte, von seiner Bilddarstellung in maschinenlesbaren Text um.
Im Allgemeinen umfasst eine OCR-Engine mehrere Schritte, die erforderlich sind, um einen maschinellen Lernalgorithmus für eine effiziente Problemlösung mit Hilfe der optischen Zeichenerkennung zu trainieren.
Die folgenden Schritte, die sich von einer Engine zur anderen unterscheiden können, sind ungefähr erforderlich, um sich der automatischen Zeichenerkennung zu nähern:
In diesem Tutorial zeige ich Ihnen Folgendes:
Bitte beachten Sie, dass es in diesem Tutorial um das Extrahieren von Text aus Bildern in PDF-Dokumenten geht.
Um zu beginnen, müssen wir die folgenden Bibliotheken verwenden:
Tesseract OCR : ist eine Open-Source-Texterkennungs-Engine, die unter der Apache 2.0-Lizenz verfügbar ist und deren Entwicklung seit 2006 von Google gesponsert wird. Im Jahr 2006 galt Tesseract als eine der genauesten Open-Source-OCR-Engines. Sie können es direkt verwenden oder die API verwenden, um den gedruckten Text aus Bildern zu extrahieren. Das Beste daran ist, dass es eine große Auswahl an Sprachen unterstützt.
Die Installation der Tesseract-Engine würde den Rahmen dieses Artikels sprengen. Sie müssen jedoch der offiziellen Installationsanleitung von Tesseract folgen , um es auf Ihrem Betriebssystem zu installieren.
Um das Tesseract-Setup zu validieren, führen Sie bitte den folgenden Befehl aus und überprüfen Sie die generierte Ausgabe:
Python-tesseract : ist ein Python-Wrapper für die Tesseract-OCR-Engine von Google. Es ist auch als eigenständiges Aufrufskript für Tesseract nützlich, da es alle Bildtypen lesen kann, die von den Pillow- und Leptonica-Imaging-Bibliotheken unterstützt werden, einschließlich jpeg, png, gif, bmp, tiff und andere.
OpenCV : ist eine Python-Open-Source-Bibliothek für Computer Vision, maschinelles Lernen und Bildverarbeitung. OpenCV unterstützt eine Vielzahl von Programmiersprachen wie Python, C++, Java usw. Es kann Bilder und Videos verarbeiten, um Objekte, Gesichter oder sogar die Handschrift eines Menschen zu identifizieren.
PyMuPDF : MuPDF ist eine äußerst vielseitige, anpassbare PDF-, XPS- und eBook-Interpreterlösung, die in einer Vielzahl von Anwendungen als PDF-Renderer, Viewer oder Toolkit verwendet werden kann. PyMuPDF ist eine Python-Bindung für MuPDF. Es ist ein leichter PDF- und XPS-Viewer.
Numpy: ist ein universelles Array-Verarbeitungspaket. Es stellt ein hochleistungsfähiges multidimensionales Array-Objekt und Tools zum Arbeiten mit diesen Arrays bereit. Es ist das grundlegende Paket für wissenschaftliches Rechnen mit Python. Außerdem kann Numpy auch als effizienter mehrdimensionaler Container für generische Daten verwendet werden.
Pillow: baut auf PIL (Python Image Library) auf. Es ist ein wesentliches Modul für die Bildverarbeitung in Python.
Pandas: ist eine BSD-lizenzierte Open-Source-Python-Bibliothek, die leistungsstarke, einfach zu verwendende Datenstrukturen und Datenanalysetools für die Programmiersprache Python bereitstellt.
Dateityp: Kleines und abhängigkeitsfreies Python-Paket zum Ableiten von Dateityp und MIME-Typ.
Dieses Tutorial zielt darauf ab, ein leichtes, befehlszeilenbasiertes Dienstprogramm zu entwickeln, um einen Text zu extrahieren, zu redigieren oder hervorzuheben, der in einem Bild oder einer gescannten PDF-Datei oder in einem Ordner enthalten ist, der eine Sammlung von PDF-Dateien enthält.
Lassen Sie uns zunächst die Anforderungen installieren:
$ pip install Filetype==1.0.7 numpy==1.19.4 opencv-python==4.4.0.46 pandas==1.1.4 Pillow==8.0.1 PyMuPDF==1.18.9 pytesseract==0.3.7
Beginnen wir mit dem Importieren der erforderlichen Bibliotheken:
import os
import re
import argparse
import pytesseract
from pytesseract import Output
import cv2
import numpy as np
import fitz
from io import BytesIO
from PIL import Image
import pandas as pd
import filetype
# Path Of The Tesseract OCR engine
TESSERACT_PATH = "C:\Program Files\Tesseract-OCR\tesseract.exe"
# Include tesseract executable
pytesseract.pytesseract.tesseract_cmd = TESSERACT_PATH
TESSERACT_PATH
Hier befindet sich die ausführbare Tesseract-Datei. Offensichtlich müssen Sie es für Ihren Fall ändern.
def pix2np(pix):
"""
Converts a pixmap buffer into a numpy array
"""
# pix.samples = sequence of bytes of the image pixels like RGBA
#pix.h = height in pixels
#pix.w = width in pixels
# pix.n = number of components per pixel (depends on the colorspace and alpha)
im = np.frombuffer(pix.samples, dtype=np.uint8).reshape(
pix.h, pix.w, pix.n)
try:
im = np.ascontiguousarray(im[..., [2, 1, 0]]) # RGB To BGR
except IndexError:
# Convert Gray to RGB
im = cv2.cvtColor(im, cv2.COLOR_GRAY2RGB)
im = np.ascontiguousarray(im[..., [2, 1, 0]]) # RGB To BGR
return im
Diese Funktion konvertiert einen Pixmap-Puffer, der einen mit der PyMuPDF-Bibliothek erstellten Screenshot darstellt, in ein NumPy-Array.
Um die Tesseract-Genauigkeit zu verbessern, definieren wir einige Vorverarbeitungsfunktionen mit OpenCV:
# Image Pre-Processing Functions to improve output accurracy
# Convert to grayscale
def grayscale(img):
return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Remove noise
def remove_noise(img):
return cv2.medianBlur(img, 5)
# Thresholding
def threshold(img):
# return cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
return cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# dilation
def dilate(img):
kernel = np.ones((5, 5), np.uint8)
return cv2.dilate(img, kernel, iterations=1)
# erosion
def erode(img):
kernel = np.ones((5, 5), np.uint8)
return cv2.erode(img, kernel, iterations=1)
# opening -- erosion followed by a dilation
def opening(img):
kernel = np.ones((5, 5), np.uint8)
return cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# canny edge detection
def canny(img):
return cv2.Canny(img, 100, 200)
# skew correction
def deskew(img):
coords = np.column_stack(np.where(img > 0))
angle = cv2.minAreaRect(coords)[-1]
if angle < -45:
angle = -(90 + angle)
else:
angle = -angle
(h, w) = img.shape[:2]
center = (w//2, h//2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(
img, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
return rotated
# template matching
def match_template(img, template):
return cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
def convert_img2bin(img):
"""
Pre-processes the image and generates a binary output
"""
# Convert the image into a grayscale image
output_img = grayscale(img)
# Invert the grayscale image by flipping pixel values.
# All pixels that are grater than 0 are set to 0 and all pixels that are = to 0 are set to 255
output_img = cv2.bitwise_not(output_img)
# Converting image to binary by Thresholding in order to show a clear separation between white and blacl pixels.
output_img = threshold(output_img)
return output_img
Wir haben Funktionen für viele Vorverarbeitungsaufgaben definiert, darunter das Konvertieren von Bildern in Graustufen, das Spiegeln von Pixelwerten, das Trennen von weißen und schwarzen Pixeln und vieles mehr.
Als nächstes definieren wir eine Funktion zum Anzeigen eines Bildes:
def display_img(title, img):
"""Displays an image on screen and maintains the output until the user presses a key"""
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.setWindowTitle('img', title)
cv2.resizeWindow('img', 1200, 900)
# Display Image on screen
cv2.imshow('img', img)
# Mantain output until user presses a key
cv2.waitKey(0)
# Destroy windows when user presses a key
cv2.destroyAllWindows()
Die display_img()
Funktion zeigt auf dem Bildschirm ein Bild in einem Fenster mit einem auf den title
Parameter gesetzten Titel an und hält dieses Fenster geöffnet, bis der Benutzer eine Taste auf der Tastatur drückt.
def generate_ss_text(ss_details):
"""Loops through the captured text of an image and arranges this text line by line.
This function depends on the image layout."""
# Arrange the captured text after scanning the page
parse_text = []
word_list = []
last_word = ''
# Loop through the captured text of the entire page
for word in ss_details['text']:
# If the word captured is not empty
if word != '':
# Add it to the line word list
word_list.append(word)
last_word = word
if (last_word != '' and word == '') or (word == ss_details['text'][-1]):
parse_text.append(word_list)
word_list = []
return parse_text
Die obige Funktion durchläuft den erfassten Text eines Bildes und ordnet den erfassten Text Zeile für Zeile an. Dies hängt vom Bildlayout ab und kann bei einigen Bildformaten eine Anpassung erfordern.
Als nächstes definieren wir eine Funktion, um mit regulären Ausdrücken nach Text zu suchen :
def search_for_text(ss_details, search_str):
"""Search for the search string within the image content"""
# Find all matches within one page
results = re.findall(search_str, ss_details['text'], re.IGNORECASE)
# In case multiple matches within one page
for result in results:
yield result
Wir werden diese Funktion verwenden, um im erfassten Inhalt eines Bildes nach bestimmtem Text zu suchen. Es gibt einen Generator der gefundenen Übereinstimmungen zurück.
def save_page_content(pdfContent, page_id, page_data):
"""Appends the content of a scanned page, line by line, to a pandas DataFrame."""
if page_data:
for idx, line in enumerate(page_data, 1):
line = ' '.join(line)
pdfContent = pdfContent.append(
{'page': page_id, 'line_id': idx, 'line': line}, ignore_index=True
)
return pdfContent
save_page_content()
Funktion hängt den erfassten Inhalt eines Bildes Zeile für Zeile an, nachdem es an den pdfContent
Pandas-Datenrahmen gescannt wurde.
Lassen Sie uns nun eine Funktion erstellen, um den resultierenden Datenrahmen in einer CSV-Datei zu speichern:
def save_file_content(pdfContent, input_file):
"""Outputs the content of the pandas DataFrame to a CSV file having the same path as the input_file
but with different extension (.csv)"""
content_file = os.path.join(os.path.dirname(input_file), os.path.splitext(
os.path.basename(input_file))[0] + ".csv")
pdfContent.to_csv(content_file, sep=',', index=False)
return content_file
Als Nächstes schreiben wir eine Funktion, die den Konfidenzwert des aus dem gescannten Bild entnommenen Textes berechnet:
def calculate_ss_confidence(ss_details: dict):
"""Calculate the confidence score of the text grabbed from the scanned image."""
# page_num --> Page number of the detected text or item
# block_num --> Block number of the detected text or item
# par_num --> Paragraph number of the detected text or item
# line_num --> Line number of the detected text or item
# Convert the dict to dataFrame
df = pd.DataFrame.from_dict(ss_details)
# Convert the field conf (confidence) to numeric
df['conf'] = pd.to_numeric(df['conf'], errors='coerce')
# Elliminate records with negative confidence
df = df[df.conf != -1]
# Calculate the mean confidence by page
conf = df.groupby(['page_num'])['conf'].mean().tolist()
return conf[0]
Zur Hauptfunktion gehen: Bild scannen:
def ocr_img(
img: np.array, input_file: str, search_str: str,
highlight_readable_text: bool = False, action: str = 'Highlight',
show_comparison: bool = False, generate_output: bool = True):
"""Scans an image buffer or an image file.
Pre-processes the image.
Calls the Tesseract engine with pre-defined parameters.
Calculates the confidence score of the image grabbed content.
Draws a green rectangle around readable text items having a confidence score > 30.
Searches for a specific text.
Highlight or redact found matches of the searched text.
Displays a window showing readable text fields or the highlighted or redacted text.
Generates the text content of the image.
Prints a summary to the console."""
# If image source file is inputted as a parameter
if input_file:
# Reading image using opencv
img = cv2.imread(input_file)
# Preserve a copy of this image for comparison purposes
initial_img = img.copy()
highlighted_img = img.copy()
# Convert image to binary
bin_img = convert_img2bin(img)
# Calling Tesseract
# Tesseract Configuration parameters
# oem --> OCR engine mode = 3 >> Legacy + LSTM mode only (LSTM neutral net mode works the best)
# psm --> page segmentation mode = 6 >> Assume as single uniform block of text (How a page of text can be analyzed)
config_param = r'--oem 3 --psm 6'
# Feeding image to tesseract
details = pytesseract.image_to_data(
bin_img, output_type=Output.DICT, config=config_param, lang='eng')
# The details dictionary contains the information of the input image
# such as detected text, region, position, information, height, width, confidence score.
ss_confidence = calculate_ss_confidence(details)
boxed_img = None
# Total readable items
ss_readable_items = 0
# Total matches found
ss_matches = 0
for seq in range(len(details['text'])):
# Consider only text fields with confidence score > 30 (text is readable)
if float(details['conf'][seq]) > 30.0:
ss_readable_items += 1
# Draws a green rectangle around readable text items having a confidence score > 30
if highlight_readable_text:
(x, y, w, h) = (details['left'][seq], details['top']
[seq], details['width'][seq], details['height'][seq])
boxed_img = cv2.rectangle(
img, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Searches for the string
if search_str:
results = re.findall(
search_str, details['text'][seq], re.IGNORECASE)
for result in results:
ss_matches += 1
if action:
# Draw a red rectangle around the searchable text
(x, y, w, h) = (details['left'][seq], details['top']
[seq], details['width'][seq], details['height'][seq])
# Details of the rectangle
# Starting coordinate representing the top left corner of the rectangle
start_point = (x, y)
# Ending coordinate representing the botton right corner of the rectangle
end_point = (x + w, y + h)
#Color in BGR -- Blue, Green, Red
if action == "Highlight":
color = (0, 255, 255) # Yellow
elif action == "Redact":
color = (0, 0, 0) # Black
# Thickness in px (-1 will fill the entire shape)
thickness = -1
boxed_img = cv2.rectangle(
img, start_point, end_point, color, thickness)
if ss_readable_items > 0 and highlight_readable_text and not (ss_matches > 0 and action in ("Highlight", "Redact")):
highlighted_img = boxed_img.copy()
# Highlight found matches of the search string
if ss_matches > 0 and action == "Highlight":
cv2.addWeighted(boxed_img, 0.4, highlighted_img,
1 - 0.4, 0, highlighted_img)
# Redact found matches of the search string
elif ss_matches > 0 and action == "Redact":
highlighted_img = boxed_img.copy()
#cv2.addWeighted(boxed_img, 1, highlighted_img, 0, 0, highlighted_img)
# save the image
cv2.imwrite("highlighted-text-image.jpg", highlighted_img)
# Displays window showing readable text fields or the highlighted or redacted data
if show_comparison and (highlight_readable_text or action):
title = input_file if input_file else 'Compare'
conc_img = cv2.hconcat([initial_img, highlighted_img])
display_img(title, conc_img)
# Generates the text content of the image
output_data = None
if generate_output and details:
output_data = generate_ss_text(details)
# Prints a summary to the console
if input_file:
summary = {
"File": input_file, "Total readable words": ss_readable_items, "Total matches": ss_matches, "Confidence score": ss_confidence
}
# Printing Summary
print("## Summary ########################################################")
print("\n".join("{}:{}".format(i, j) for i, j in summary.items()))
print("###################################################################")
return highlighted_img, ss_readable_items, ss_matches, ss_confidence, output_data
# pass image into pytesseract module
# pytesseract is trained in many languages
#config_param = r'--oem 3 --psm 6'
#details = pytesseract.image_to_data(img,config=config_param,lang='eng')
# print(details)
# return details
Das obige führt Folgendes aus:
def image_to_byte_array(image: Image):
"""
Converts an image into a byte array
"""
imgByteArr = BytesIO()
image.save(imgByteArr, format=image.format if image.format else 'JPEG')
imgByteArr = imgByteArr.getvalue()
return imgByteArr
def ocr_file(**kwargs):
"""Opens the input PDF File.
Opens a memory buffer for storing the output PDF file.
Creates a DataFrame for storing pages statistics
Iterates throughout the chosen pages of the input PDF file
Grabs a screen-shot of the selected PDF page.
Converts the screen-shot pix to a numpy array
Scans the grabbed screen-shot.
Collects the statistics of the screen-shot(page).
Saves the content of the screen-shot(page).
Adds the updated screen-shot (Highlighted, Redacted) to the output file.
Saves the whole content of the PDF file.
Saves the output PDF file if required.
Prints a summary to the console."""
input_file = kwargs.get('input_file')
output_file = kwargs.get('output_file')
search_str = kwargs.get('search_str')
pages = kwargs.get('pages')
highlight_readable_text = kwargs.get('highlight_readable_text')
action = kwargs.get('action')
show_comparison = kwargs.get('show_comparison')
generate_output = kwargs.get('generate_output')
# Opens the input PDF file
pdfIn = fitz.open(input_file)
# Opens a memory buffer for storing the output PDF file.
pdfOut = fitz.open()
# Creates an empty DataFrame for storing pages statistics
dfResult = pd.DataFrame(
columns=['page', 'page_readable_items', 'page_matches', 'page_total_confidence'])
# Creates an empty DataFrame for storing file content
if generate_output:
pdfContent = pd.DataFrame(columns=['page', 'line_id', 'line'])
# Iterate throughout the pages of the input file
for pg in range(pdfIn.pageCount):
if str(pages) != str(None):
if str(pg) not in str(pages):
continue
# Select a page
page = pdfIn[pg]
# Rotation angle
rotate = int(0)
# PDF Page is converted into a whole picture 1056*816 and then for each picture a screenshot is taken.
# zoom = 1.33333333 -----> Image size = 1056*816
# zoom = 2 ---> 2 * Default Resolution (text is clear, image text is hard to read) = filesize small / Image size = 1584*1224
# zoom = 4 ---> 4 * Default Resolution (text is clear, image text is barely readable) = filesize large
# zoom = 8 ---> 8 * Default Resolution (text is clear, image text is readable) = filesize large
zoom_x = 2
zoom_y = 2
# The zoom factor is equal to 2 in order to make text clear
# Pre-rotate is to rotate if needed.
mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
# To captue a specific part of the PDF page
# rect = page.rect #page size
# mp = rect.tl + (rect.bl - (0.75)/zoom_x) #rectangular area 56 = 75/1.3333
# clip = fitz.Rect(mp,rect.br) #The area to capture
# pix = page.getPixmap(matrix=mat, alpha=False,clip=clip)
# Get a screen-shot of the PDF page
# Colorspace -> represents the color space of the pixmap (csRGB, csGRAY, csCMYK)
# alpha -> Transparancy indicator
pix = page.getPixmap(matrix=mat, alpha=False, colorspace="csGRAY")
# convert the screen-shot pix to numpy array
img = pix2np(pix)
# Erode image to omit or thin the boundaries of the bright area of the image
# We apply Erosion on binary images.
#kernel = np.ones((2,2) , np.uint8)
#img = cv2.erode(img,kernel,iterations=1)
upd_np_array, pg_readable_items, pg_matches, pg_total_confidence, pg_output_data \
= ocr_img(img=img, input_file=None, search_str=search_str, highlight_readable_text=highlight_readable_text # False
, action=action # 'Redact'
, show_comparison=show_comparison # True
, generate_output=generate_output # False
)
# Collects the statistics of the page
dfResult = dfResult.append({'page': (pg+1), 'page_readable_items': pg_readable_items,
'page_matches': pg_matches, 'page_total_confidence': pg_total_confidence}, ignore_index=True)
if generate_output:
pdfContent = save_page_content(
pdfContent=pdfContent, page_id=(pg+1), page_data=pg_output_data)
# Convert the numpy array to image object with mode = RGB
#upd_img = Image.fromarray(np.uint8(upd_np_array)).convert('RGB')
upd_img = Image.fromarray(upd_np_array[..., ::-1])
# Convert the image to byte array
upd_array = image_to_byte_array(upd_img)
# Get Page Size
"""
#To check whether initial page is portrait or landscape
if page.rect.width > page.rect.height:
fmt = fitz.PaperRect("a4-1")
else:
fmt = fitz.PaperRect("a4")
#pno = -1 -> Insert after last page
pageo = pdfOut.newPage(pno = -1, width = fmt.width, height = fmt.height)
"""
pageo = pdfOut.newPage(
pno=-1, width=page.rect.width, height=page.rect.height)
pageo.insertImage(page.rect, stream=upd_array)
#pageo.insertImage(page.rect, stream=upd_img.tobytes())
#pageo.showPDFpage(pageo.rect, pdfDoc, page.number)
content_file = None
if generate_output:
content_file = save_file_content(
pdfContent=pdfContent, input_file=input_file)
summary = {
"File": input_file, "Total pages": pdfIn.pageCount,
"Processed pages": dfResult['page'].count(), "Total readable words": dfResult['page_readable_items'].sum(),
"Total matches": dfResult['page_matches'].sum(), "Confidence score": dfResult['page_total_confidence'].mean(),
"Output file": output_file, "Content file": content_file
}
# Printing Summary
print("## Summary ########################################################")
print("\n".join("{}:{}".format(i, j) for i, j in summary.items()))
print("\nPages Statistics:")
print(dfResult, sep='\n')
print("###################################################################")
pdfIn.close()
if output_file:
pdfOut.save(output_file)
pdfOut.close()
Die image_to_byte_array()
Funktion konvertiert ein Bild in ein Byte-Array.
Die ocr_file()
Funktion macht folgendes:
Fügen wir eine weitere Funktion zum Verarbeiten eines Ordners hinzu, der mehrere PDF-Dateien enthält:
def ocr_folder(**kwargs):
"""Scans all PDF Files within a specified path"""
input_folder = kwargs.get('input_folder')
# Run in recursive mode
recursive = kwargs.get('recursive')
search_str = kwargs.get('search_str')
pages = kwargs.get('pages')
action = kwargs.get('action')
generate_output = kwargs.get('generate_output')
# Loop though the files within the input folder.
for foldername, dirs, filenames in os.walk(input_folder):
for filename in filenames:
# Check if pdf file
if not filename.endswith('.pdf'):
continue
# PDF File found
inp_pdf_file = os.path.join(foldername, filename)
print("Processing file =", inp_pdf_file)
output_file = None
if search_str:
# Generate an output file
output_file = os.path.join(os.path.dirname(
inp_pdf_file), 'ocr_' + os.path.basename(inp_pdf_file))
ocr_file(
input_file=inp_pdf_file, output_file=output_file, search_str=search_str, pages=pages, highlight_readable_text=False, action=action, show_comparison=False, generate_output=generate_output
)
if not recursive:
break
Diese Funktion soll die PDF-Dateien scannen, die in einem bestimmten Ordner enthalten sind. Es durchläuft die Dateien des angegebenen Ordners entweder rekursiv oder nicht, abhängig vom Wert des Parameters recursive, und verarbeitet diese Dateien eine nach der anderen.
Es akzeptiert die folgenden Parameter:
input_folder
: Der Pfad des Ordners, der die zu verarbeitenden PDF-Dateien enthält.search_str
: Der Text, nach dem gesucht werden soll, um bearbeitet zu werden.recursive
: ob dieser Prozess rekursiv ausgeführt werden soll, indem die Unterordner durchlaufen werden oder nicht.action
: die auszuführende Aktion unter den folgenden: Hervorheben, Schwärzen.pages
: die zu berücksichtigenden Seiten.generate_output
: Wählen Sie aus, ob der Inhalt der eingegebenen PDF-Datei in einer CSV-Datei gespeichert werden soll oder nichtBevor wir fertig sind, definieren wir nützliche Funktionen zum Analysieren von Befehlszeilenargumenten:
def is_valid_path(path):
"""Validates the path inputted and checks whether it is a file path or a folder path"""
if not path:
raise ValueError(f"Invalid Path")
if os.path.isfile(path):
return path
elif os.path.isdir(path):
return path
else:
raise ValueError(f"Invalid Path {path}")
def parse_args():
"""Get user command line parameters"""
parser = argparse.ArgumentParser(description="Available Options")
parser.add_argument('-i', '--input-path', type=is_valid_path,
required=True, help="Enter the path of the file or the folder to process")
parser.add_argument('-a', '--action', choices=[
'Highlight', 'Redact'], type=str, help="Choose to highlight or to redact")
parser.add_argument('-s', '--search-str', dest='search_str',
type=str, help="Enter a valid search string")
parser.add_argument('-p', '--pages', dest='pages', type=tuple,
help="Enter the pages to consider in the PDF file, e.g. (0,1)")
parser.add_argument("-g", "--generate-output", action="store_true", help="Generate text content in a CSV file")
path = parser.parse_known_args()[0].input_path
if os.path.isfile(path):
parser.add_argument('-o', '--output_file', dest='output_file',
type=str, help="Enter a valid output file")
parser.add_argument("-t", "--highlight-readable-text", action="store_true", help="Highlight readable text in the generated image")
parser.add_argument("-c", "--show-comparison", action="store_true", help="Show comparison between captured image and the generated image")
if os.path.isdir(path):
parser.add_argument("-r", "--recursive", action="store_true", help="Whether to process the directory recursively")
# To Porse The Command Line Arguments
args = vars(parser.parse_args())
# To Display The Command Line Arguments
print("## Command Arguments #################################################")
print("\n".join("{}:{}".format(i, j) for i, j in args.items()))
print("######################################################################")
return args
Die is_valid_path()
Funktion validiert einen als Parameter eingegebenen Pfad und prüft, ob es sich um einen Dateipfad oder einen Verzeichnispfad handelt.
Die parse_args()
Funktion definiert und legt die entsprechenden Einschränkungen für die Befehlszeilenargumente des Benutzers fest, wenn dieses Dienstprogramm ausgeführt wird.
Nachfolgend finden Sie Erläuterungen zu allen Parametern:
input_path
: Ein erforderlicher Parameter zur Eingabe des Pfads der zu verarbeitenden Datei oder des zu verarbeitenden Ordners. Dieser Parameter ist mit der is_valid_path()
zuvor definierten Funktion verknüpft.action
: Die Aktion, die in einer Liste vordefinierter Optionen ausgeführt werden soll, um eine fehlerhafte Auswahl zu vermeiden.search_str
: Der Text, nach dem gesucht werden soll, um bearbeitet zu werden.pages
: die Seiten, die bei der Verarbeitung einer PDF-Datei zu berücksichtigen sind.generate_content
: Gibt an, ob der erfasste Inhalt der Eingabedatei, ob ein Bild oder eine PDF-Datei, in eine CSV-Datei umgewandelt werden soll oder nicht.output_file
: Der Pfad der Ausgabedatei. Das Ausfüllen dieses Arguments wird durch die Auswahl einer Datei als Eingabe eingeschränkt, nicht eines Verzeichnisses.highlight_readable_text
: Grüne Rechtecke um lesbare Textfelder mit einem Konfidenzwert von mehr als 30 zeichnen.show_comparison
: Zeigt ein Fenster mit einem Vergleich zwischen dem Originalbild und dem verarbeiteten Bild an.recursive
: ob ein Ordner rekursiv verarbeitet werden soll oder nicht. Das Ausfüllen dieses Arguments wird durch die Auswahl eines Verzeichnisses eingeschränkt.Schreiben wir zum Schluss den Hauptcode, der zuvor definierte Funktionen verwendet:
if __name__ == '__main__':
# Parsing command line arguments entered by user
args = parse_args()
# If File Path
if os.path.isfile(args['input_path']):
# Process a file
if filetype.is_image(args['input_path']):
ocr_img(
# if 'search_str' in (args.keys()) else None
img=None, input_file=args['input_path'], search_str=args['search_str'], highlight_readable_text=args['highlight_readable_text'], action=args['action'], show_comparison=args['show_comparison'], generate_output=args['generate_output']
)
else:
ocr_file(
input_file=args['input_path'], output_file=args['output_file'], search_str=args['search_str'] if 'search_str' in (args.keys()) else None, pages=args['pages'], highlight_readable_text=args['highlight_readable_text'], action=args['action'], show_comparison=args['show_comparison'], generate_output=args['generate_output']
)
# If Folder Path
elif os.path.isdir(args['input_path']):
# Process a folder
ocr_folder(
input_folder=args['input_path'], recursive=args['recursive'], search_str=args['search_str'] if 'search_str' in (args.keys()) else None, pages=args['pages'], action=args['action'], generate_output=args['generate_output']
)
Testen wir unser Programm:
$ python pdf_ocr.py
Ausgabe:
usage: pdf_ocr.py [-h] -i INPUT_PATH [-a {Highlight,Redact}] [-s SEARCH_STR] [-p PAGES] [-g GENERATE_OUTPUT]
Available Options
optional arguments:
-h, --help show this help message and exit
-i INPUT_PATH, --input_path INPUT_PATH
Enter the path of the file or the folder to process
-a {Highlight,Redact}, --action {Highlight,Redact}
Choose to highlight or to redact
-s SEARCH_STR, --search_str SEARCH_STR
Enter a valid search string
-p PAGES, --pages PAGES
Enter the pages to consider e.g.: (0,1)
-g GENERATE_OUTPUT, --generate_output GENERATE_OUTPUT
Generate content in a CSV file
Beachten Sie Folgendes, bevor Sie unsere Testszenarien untersuchen:
PermissionError
diesen Fehler zu vermeiden, schließen Sie bitte die Eingabedatei, bevor Sie dieses Dienstprogramm ausführen.Lassen Sie uns zunächst versuchen, ein Bild einzugeben (Sie können es hier abrufen, wenn Sie die gleiche Ausgabe erhalten möchten), ohne dass eine PDF-Datei beteiligt ist:
$ python pdf_ocr.py -s "BERT" -a Highlight -i example-image-containing-text.jpg
Folgendes wird die Ausgabe sein:
## Command Arguments #################################################
input_path:example-image-containing-text.jpg
action:Highlight
search_str:BERT
pages:None
generate_output:False
output_file:None
highlight_readable_text:False
show_comparison:False
######################################################################
## Summary ########################################################
File:example-image-containing-text.jpg
Total readable words:192
Total matches:3
Confidence score:89.89337547979804
###################################################################
Und im aktuellen Verzeichnis ist ein neues Bild erschienen:
Sie können den gesamten erkannten Text übergeben
-t
oder --highlight-readable-text
hervorheben (mit einem anderen Format, um die Suchzeichenfolge von den anderen zu unterscheiden).
Sie können auch übergeben -c
oder --show-comparison
das Originalbild und das bearbeitete Bild im selben Fenster anzeigen.
Das funktioniert jetzt für Bilder, versuchen wir es mit PDF-Dateien:
$ python pdf_ocr.py -s "BERT" -i image.pdf -o output.pdf --generate-output -a "Highlight"
image.pdf
ist eine einfache PDF-Datei, die das Bild im vorherigen Beispiel enthält (auch hier können Sie es abrufen ).
Dieses Mal haben wir eine PDF-Datei an das -i
Argument und output.pdf
als resultierende PDF-Datei übergeben (in der die gesamte Hervorhebung erfolgt). Der obige Befehl erzeugt die folgende Ausgabe:
## Command Arguments #################################################
input_path:image.pdf
action:Highlight
search_str:BERT
pages:None
generate_output:True
output_file:output.pdf
highlight_readable_text:False
show_comparison:False
######################################################################
## Summary ########################################################
File:image.pdf
Total pages:1
Processed pages:1
Total readable words:192.0
Total matches:3.0
Confidence score:83.1775128855722
Output file:output.pdf
Content file:image.csv
Pages Statistics:
page page_readable_items page_matches page_total_confidence
0 1.0 192.0 3.0 83.177513
###################################################################
Die output.pdf
Datei wird nach der Ausführung erstellt, wobei sie das gleiche Original-PDF enthält, jedoch mit hervorgehobenem Text. Darüber hinaus haben wir jetzt Statistiken über unsere PDF-Datei, in der insgesamt 192 Wörter erkannt wurden und 3 mit unserer Suche mit einer Zuverlässigkeit von etwa 83,2 % abgeglichen wurden.
Außerdem wird eine CSV-Datei generiert, die den erkannten Text aus dem Bild in jeder Zeile enthält.
Es gibt andere Parameter, die wir in unseren Beispielen nicht verwendet haben, fühlen Sie sich frei, sie zu erkunden. Sie können auch einen ganzen Ordner an das -i
Argument übergeben, um eine Sammlung von PDF-Dateien zu scannen.
Tesseract ist perfekt zum Scannen sauberer und klarer Dokumente. Ein Scan von schlechter Qualität kann zu schlechten OCR-Ergebnissen führen. Normalerweise liefert es keine genauen Ergebnisse der Bilder, die von Artefakten wie teilweiser Okklusion, verzerrter Perspektive und komplexem Hintergrund betroffen sind.
Quelle des Originalartikels unter https://www.thepythoncode.com
1626775355
No programming language is pretty much as diverse as Python. It enables building cutting edge applications effortlessly. Developers are as yet investigating the full capability of end-to-end Python development services in various areas.
By areas, we mean FinTech, HealthTech, InsureTech, Cybersecurity, and that's just the beginning. These are New Economy areas, and Python has the ability to serve every one of them. The vast majority of them require massive computational abilities. Python's code is dynamic and powerful - equipped for taking care of the heavy traffic and substantial algorithmic capacities.
Programming advancement is multidimensional today. Endeavor programming requires an intelligent application with AI and ML capacities. Shopper based applications require information examination to convey a superior client experience. Netflix, Trello, and Amazon are genuine instances of such applications. Python assists with building them effortlessly.
Python can do such numerous things that developers can't discover enough reasons to admire it. Python application development isn't restricted to web and enterprise applications. It is exceptionally adaptable and superb for a wide range of uses.
Robust frameworks
Python is known for its tools and frameworks. There's a structure for everything. Django is helpful for building web applications, venture applications, logical applications, and mathematical processing. Flask is another web improvement framework with no conditions.
Web2Py, CherryPy, and Falcon offer incredible capabilities to customize Python development services. A large portion of them are open-source frameworks that allow quick turn of events.
Simple to read and compose
Python has an improved sentence structure - one that is like the English language. New engineers for Python can undoubtedly understand where they stand in the development process. The simplicity of composing allows quick application building.
The motivation behind building Python, as said by its maker Guido Van Rossum, was to empower even beginner engineers to comprehend the programming language. The simple coding likewise permits developers to roll out speedy improvements without getting confused by pointless subtleties.
Utilized by the best
Alright - Python isn't simply one more programming language. It should have something, which is the reason the business giants use it. Furthermore, that too for different purposes. Developers at Google use Python to assemble framework organization systems, parallel information pusher, code audit, testing and QA, and substantially more. Netflix utilizes Python web development services for its recommendation algorithm and media player.
Massive community support
Python has a steadily developing community that offers enormous help. From amateurs to specialists, there's everybody. There are a lot of instructional exercises, documentation, and guides accessible for Python web development solutions.
Today, numerous universities start with Python, adding to the quantity of individuals in the community. Frequently, Python designers team up on various tasks and help each other with algorithmic, utilitarian, and application critical thinking.
Progressive applications
Python is the greatest supporter of data science, Machine Learning, and Artificial Intelligence at any enterprise software development company. Its utilization cases in cutting edge applications are the most compelling motivation for its prosperity. Python is the second most well known tool after R for data analytics.
The simplicity of getting sorted out, overseeing, and visualizing information through unique libraries makes it ideal for data based applications. TensorFlow for neural networks and OpenCV for computer vision are two of Python's most well known use cases for Machine learning applications.
Thinking about the advances in programming and innovation, Python is a YES for an assorted scope of utilizations. Game development, web application development services, GUI advancement, ML and AI improvement, Enterprise and customer applications - every one of them uses Python to its full potential.
The disadvantages of Python web improvement arrangements are regularly disregarded by developers and organizations because of the advantages it gives. They focus on quality over speed and performance over blunders. That is the reason it's a good idea to utilize Python for building the applications of the future.
#python development services #python development company #python app development #python development #python in web development #python software development
1624428000
The Portable Document Format (PDF) is not a WYSIWYG (What You See is What You Get) format. It was developed to be platform-agnostic, independent of the underlying operating system and rendering engines.
To achieve this, PDF was constructed to be interacted with via something more like a programming language, and relies on a series of instructions and operations to achieve a result. In fact, PDF is based on a scripting language - PostScript, which was the first device-independent Page Description Language.
In this guide, we’ll be using pText - a Python library dedicated to reading, manipulating and generating PDF documents. It offers both a low-level model (allowing you access to the exact coordinates and layout if you choose to use those) and a high-level model (where you can delegate the precise calculations of margins, positions, etc to a layout manager).
We’ll take a look at how to create a PDF invoice in Python using pText.
#python #pdf #creating pdf invoices in python with ptext #creating pdf invoices #pdf invoice #creating pdf invoices in python with ptext
1650870267
In the previous chapters you've learnt how to select individual elements on a web page. But there are many occasions where you need to access a child, parent or ancestor element. See the JavaScript DOM nodes chapter to understand the logical relationships between the nodes in a DOM tree.
DOM node provides several properties and methods that allow you to navigate or traverse through the tree structure of the DOM and make changes very easily. In the following section we will learn how to navigate up, down, and sideways in the DOM tree using JavaScript.
You can use the firstChild
and lastChild
properties of the DOM node to access the first and last direct child node of a node, respectively. If the node doesn't have any child element, it returns null
.
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
console.log(main.firstChild.nodeName); // Prints: #text
var hint = document.getElementById("hint");
console.log(hint.firstChild.nodeName); // Prints: SPAN
</script>
Note: The
nodeName
is a read-only property that returns the name of the current node as a string. For example, it returns the tag name for element node,#text
for text node,#comment
for comment node,#document
for document node, and so on.
If you notice the above example, the nodeName
of the first-child node of the main DIV element returns #text instead of H1. Because, whitespace such as spaces, tabs, newlines, etc. are valid characters and they form #text nodes and become a part of the DOM tree. Therefore, since the <div>
tag contains a newline before the <h1>
tag, so it will create a #text node.
To avoid the issue with firstChild
and lastChild
returning #text or #comment nodes, you could alternatively use the firstElementChild
and lastElementChild
properties to return only the first and last element node, respectively. But, it will not work in IE 9 and earlier.
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
alert(main.firstElementChild.nodeName); // Outputs: H1
main.firstElementChild.style.color = "red";
var hint = document.getElementById("hint");
alert(hint.firstElementChild.nodeName); // Outputs: SPAN
hint.firstElementChild.style.color = "blue";
</script>
Similarly, you can use the childNodes
property to access all child nodes of a given element, where the first child node is assigned index 0. Here's an example:
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
// First check that the element has child nodes
if(main.hasChildNodes()) {
var nodes = main.childNodes;
// Loop through node list and display node name
for(var i = 0; i < nodes.length; i++) {
alert(nodes[i].nodeName);
}
}
</script>
The childNodes
returns all child nodes, including non-element nodes like text and comment nodes. To get a collection of only elements, use children
property instead.
<div id="main">
<h1 id="title">My Heading</h1>
<p id="hint"><span>This is some text.</span></p>
</div>
<script>
var main = document.getElementById("main");
// First check that the element has child nodes
if(main.hasChildNodes()) {
var nodes = main.children;
// Loop through node list and display node name
for(var i = 0; i < nodes.length; i++) {
alert(nodes[i].nodeName);
}
}
</script>
1599758100
Learn how to convert your Text into Voice with Python and Google APIs
Text to speech is a process to convert any text into voice. Text to speech project takes words on digital devices and convert them into audio with a button click or finger touch. Text to speech python project is very helpful for people who are struggling with reading.
To implement this project, we will use the basic concepts of Python, Tkinter, gTTS, and playsound libraries.
To install the required libraries, you can use pip install command:
pip install tkinter
pip install gTTS
pip install playsound
Please download the source code of Text to Speech Project: Python Text to Speech
The objective of this project is to convert the text into voice with the click of a button. This project will be developed using Tkinter, gTTs, and playsound library.
In this project, we add a message which we want to convert into voice and click on play button to play the voice of that text message.
So these are the basic steps that we will do in this Python project. Let’s start.
#python tutorials #python project #python project for beginners #python text to speech #text to speech convertor #python
1602968400
Python is awesome, it’s one of the easiest languages with simple and intuitive syntax but wait, have you ever thought that there might ways to write your python code simpler?
In this tutorial, you’re going to learn a variety of Python tricks that you can use to write your Python code in a more readable and efficient way like a pro.
Swapping value in Python
Instead of creating a temporary variable to hold the value of the one while swapping, you can do this instead
>>> FirstName = "kalebu"
>>> LastName = "Jordan"
>>> FirstName, LastName = LastName, FirstName
>>> print(FirstName, LastName)
('Jordan', 'kalebu')
#python #python-programming #python3 #python-tutorials #learn-python #python-tips #python-skills #python-development