pdf-ocr / app.py
etrotta's picture
first
91acf95
import pathlib
import streamlit as st
from PIL import Image, ImageDraw, ImageFont
from streamlit_image_coordinates import streamlit_image_coordinates
import pytesseract
import pypdfium2
from streamlit.runtime.uploaded_file_manager import UploadedFile
LANG = "eng+por"
OPTIONS = ""
FONT_FILE = pathlib.Path(__file__).parent / "Roboto-Regular.ttf"
st.set_page_config(
page_title="Streamlit Demo",
layout="wide",
page_icon="🪟",
)
"# Streamlit PDF OCR Demo"
@st.cache_data(hash_funcs={"file": lambda uploaded_file: hash(uploaded_file.file_id)})
def convert_pdf_to_img(file: UploadedFile) -> Image.Image:
doc = pypdfium2.PdfDocument(file)
raw_image: pypdfium2.PdfBitmap = doc[0].render(scale=2, grayscale=True)
image: Image.Image = raw_image.to_pil()
return image
@st.cache_data
def load_image_and_ocr(img: Image.Image, lang: str, config: str) -> tuple[Image.Image, dict, list[dict]]:
data = pytesseract.image_to_data(img, lang, config, output_type=pytesseract.Output.DICT)
_boxes = [{"text": text} for text in data["text"]]
for key in ("left", "top", "width", "height"):
for i, val in enumerate(data[key]):
_boxes[i][key] = val
boxes = [box for box in _boxes if box['text'].strip() != '']
return img.convert("RGB"), data, boxes
def main(image: Image.Image):
img, data, boxes = load_image_and_ocr(image, LANG, OPTIONS)
if (coords := st.session_state.get("image_coords")) is None:
coords = {"x": 0, "y": 0}
draw = ImageDraw.Draw(img)
text = None
for box in boxes:
MARGIN = 5
x1, y1, width, height = (box['left'], box['top'], box['width'], box['height'])
x2, y2 = x1+width, y1+height
x1, y1, x2, y2 = (x1-MARGIN, y1-MARGIN, x2+MARGIN, y2+MARGIN)
if (x1 <= coords["x"] <= x2) and (y1 <= coords["y"] <= y2):
color = "blue"
font = ImageFont.FreeTypeFont(FONT_FILE, size=24)
text = box['text']
# draw.text((0, 15), text, fill="black", font=font)
draw.text(((x1+x2)/2, y1-15), text, align="center", anchor="mm", fill="red", font=font)
else:
color = "green"
draw.rectangle((x1, y1, x2, y2), fill=None, outline=color, width=2)
"## Click at a rectangle"
if text:
f'''### Selected text: "{text}"'''
else:
'''### Selected text will appear here'''
# Another option would be `click_and_drag=True` with single-word orientation mode
streamlit_image_coordinates(img, key="image_coords", click_and_drag=False)
st.file_uploader("Upload PDF", ".pdf", key="pdf")
if (pdf_file := st.session_state.get("pdf")) is not None:
base_image = convert_pdf_to_img(pdf_file)
main(base_image)