A simple Python package for OCR with searchable PDF generation using PaddleOCR
Project description
PaddleOCR Python Project
pdf-searchable-ocr
A simple and powerful Python package for Optical Character Recognition (OCR) with searchable PDF generation using PaddleOCR.
Features
- 🔍 High-accuracy OCR using PaddleOCR
- 📄 Searchable PDF generation with invisible text layers
- 🎨 Bounding box visualization for OCR results
- 🌍 Multi-language support (80+ languages)
- ⚡ GPU acceleration support
- 🔧 Simple class-based API
- 📦 Easy installation and usage
Installation
Using pip (recommended)
pip install pdf-searchable-ocr
Using uv (for development)
git clone <repository-url>
cd pdf-searchable-ocr
uv sync
Quick Start
Basic Usage
from py_ocr import OCRProcessor
# Initialize the OCR processor
ocr = OCRProcessor(lang='en', verbose=True)
# Process an image
ocr_result = ocr.process_image('path/to/your/image.jpg')
# Create a searchable PDF
pdf_path = ocr.create_searchable_pdf('path/to/your/image.jpg', ocr_result)
# Draw bounding boxes for visualization
boxed_image = ocr.draw_bounding_boxes('path/to/your/image.jpg', ocr_result)
print(f"Searchable PDF created: {pdf_path}")
print(f"Image with bounding boxes: {boxed_image}")
CLI Usage
The package also provides a command-line tool:
# Basic usage - creates searchable PDF only
pdf-searchable-ocr input.jpg
# Specify custom output PDF name
pdf-searchable-ocr input.jpg --output-pdf my_document.pdf
# Enable bounding box visualization
pdf-searchable-ocr input.jpg --bounding-boxes
# Full options with custom names
pdf-searchable-ocr invoice.jpg \
--output-pdf invoice_searchable.pdf \
--output-prefix invoice_processed \
--bounding-boxes \
--lang en
Complete Workflow
from py_ocr import OCRProcessor
# Initialize processor
ocr = OCRProcessor(lang='en', use_gpu=False, verbose=True)
# Process image with custom PDF name and bounding boxes enabled
results = ocr.process_and_generate_all(
'invoice.jpg',
output_pdf='invoice_searchable.pdf',
output_prefix='invoice_processed',
bounding_boxes=True
)
if results['searchable_pdf']:
print(f"✅ Searchable PDF: {results['searchable_pdf']}")
if results['boxed_image']:
print(f"✅ Visualization: {results['boxed_image']}")
# Or use defaults (no bounding boxes)
results = ocr.process_and_generate_all('document.jpg')
Using Sample Images
from py_ocr import OCRProcessor
# Initialize processor
ocr = OCRProcessor()
# Download a sample image for testing
image_path = ocr.download_sample_image()
# Process with custom settings
results = ocr.process_and_generate_all(
image_path,
output_pdf='sample_searchable.pdf',
output_prefix='sample',
bounding_boxes=True # Enable visualization
)
API Reference
OCRProcessor Class
__init__(lang='en', use_gpu=False, verbose=True, **kwargs)
Initialize the OCR processor.
Parameters:
lang(str): Language for OCR recognition (default: 'en')use_gpu(bool): Whether to use GPU acceleration (default: False)verbose(bool): Whether to print verbose output (default: True)**kwargs: Additional arguments passed to PaddleOCR
process_image(image_path: str) -> Dict[str, Any]
Perform OCR on an image.
Parameters:
image_path(str): Path to the image file
Returns:
dict: OCR results containing texts, scores, and bounding boxesNone: If OCR failed
create_searchable_pdf(image_path: str, ocr_result: dict, output_pdf: str) -> str
Create a searchable PDF with invisible text layers.
Parameters:
image_path(str): Path to the source imageocr_result(dict): OCR results fromprocess_image()output_pdf(str): Output PDF filename (default: "searchable_output.pdf")
Returns:
str: Path to the created PDFNone: If creation failed
draw_bounding_boxes(image_path: str, ocr_result: dict, output_image: str) -> str
Draw bounding boxes on the image to visualize OCR detection.
Parameters:
image_path(str): Path to the source imageocr_result(dict): OCR results fromprocess_image()output_image(str): Output image filename (default: "image_with_boxes.jpg")
Returns:
str: Path to the image with bounding boxesNone: If creation failed
process_and_generate_all(image_path: str, output_pdf: str, output_prefix: str, bounding_boxes: bool) -> dict
Complete workflow: OCR + Searchable PDF + Optional Bounding Box Image.
Parameters:
image_path(str): Path to the input imageoutput_pdf(str): Output PDF filename (default: "searchable_output.pdf")output_prefix(str): Prefix for output files (default: "output")bounding_boxes(bool): Whether to generate bounding box visualization (default: False)
Returns:
dict: Dictionary containing paths to all generated files
Supported Languages
pdf-searchable-ocr supports 80+ languages through PaddleOCR. Some popular ones include:
en- Englishch- Chinese (Simplified)french- Frenchgerman- Germankorean- Koreanjapan- Japaneseit- Italianxi- Spanishru- Russianar- Arabic
For the complete list, see PaddleOCR documentation.
Advanced Configuration
Output Control
# Control output files and features
ocr = OCRProcessor(lang='en')
# Minimal processing - only searchable PDF
results = ocr.process_and_generate_all(
'document.jpg',
output_pdf='my_document.pdf',
bounding_boxes=False # Skip visualization
)
# Full processing with custom names
results = ocr.process_and_generate_all(
'invoice.jpg',
output_pdf='invoice_searchable.pdf',
output_prefix='invoice_analysis',
bounding_boxes=True # Include visualization
)
# Generated files:
# - invoice_searchable.pdf (searchable PDF)
# - invoice_analysis_with_boxes.jpg (visualization)
GPU Acceleration
# Enable GPU acceleration (requires CUDA)
ocr = OCRProcessor(lang='en', use_gpu=True)
Custom PaddleOCR Settings
# Pass additional PaddleOCR parameters
ocr = OCRProcessor(
lang='en',
use_angle_cls=True, # Enable angle classification
use_textline_orientation=True, # Enable text line orientation
det_model_dir='custom/det/path', # Custom detection model
rec_model_dir='custom/rec/path' # Custom recognition model
)
Batch Processing
from py_ocr import OCRProcessor
import os
ocr = OCRProcessor(lang='en')
# Process multiple images
image_folder = 'path/to/images'
for filename in os.listdir(image_folder):
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tiff')):
image_path = os.path.join(image_folder, filename)
base_name = os.path.splitext(filename)[0]
# Process with custom output names
results = ocr.process_and_generate_all(
image_path,
output_pdf=f"searchable_{base_name}.pdf",
output_prefix=f"processed_{base_name}",
bounding_boxes=True # Generate visualizations
)
print(f"Processed: {filename}")
Output Examples
Console Output
🔧 Initializing OCR engine with language: en
✅ OCR engine initialized successfully
📁 Using existing sample image: sample_image.jpg
🔍 Processing image: sample_image.jpg
📊 Text blocks detected: 48 | Average confidence: 0.984
✅ Searchable PDF saved as: my_document.pdf
🎨 Drawing 48 bounding boxes on image...
✅ Image with bounding boxes saved as: output_with_boxes.jpg
Generated Files
When using bounding_boxes=True:
my_document.pdf- Searchable PDF with invisible text layersoutput_with_boxes.jpg- Original image with colored bounding boxes
When using bounding_boxes=False (default):
my_document.pdf- Searchable PDF only (faster processing)
Requirements
- Python >= 3.8
- PaddleOCR >= 2.7.0
- OpenCV >= 4.0
- ReportLab >= 4.0
- Pillow >= 8.0
Installation from Source
# Clone the repository
git clone <repository-url>
cd pdf-searchable-ocr
# Install with uv (recommended for development)
uv sync
# Or install with pip
pip install -e .
Development
Running Tests
uv run python -m pytest tests/
Code Formatting
uv run black py_ocr/
uv run isort py_ocr/
Type Checking
uv run mypy py_ocr/
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- PaddleOCR for the excellent OCR engine
- ReportLab for PDF generation capabilities
- OpenCV for image processing
Changelog
v0.1.0
- Initial release
- Basic OCR functionality
- Searchable PDF generation
- Bounding box visualization
- Multi-language support
Support
If you encounter any issues or have questions:
- Check the Issues page
- Create a new issue with detailed information
- Contact the maintainers
Roadmap
- Web interface for easy usage
- Batch processing CLI tool
- Docker container
- Additional output formats (Excel, Word)
- OCR result caching
- Performance optimizations
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pdf_searchable_ocr-0.1.1.tar.gz.
File metadata
- Download URL: pdf_searchable_ocr-0.1.1.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
103611c1e4f231d38883d888692baf99ef2654bc90e96bf04ee73f002ec11941
|
|
| MD5 |
d3c62010d081655de4c1112536eee6eb
|
|
| BLAKE2b-256 |
00ca3a1fded56e0e65e4f961e4d9b62715eabe3da7a93fb150495b039d8ecb04
|
Provenance
The following attestation bundles were made for pdf_searchable_ocr-0.1.1.tar.gz:
Publisher:
package-publish.yml on jasminmistry/pdf-searchable-ocr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_searchable_ocr-0.1.1.tar.gz -
Subject digest:
103611c1e4f231d38883d888692baf99ef2654bc90e96bf04ee73f002ec11941 - Sigstore transparency entry: 597490104
- Sigstore integration time:
-
Permalink:
jasminmistry/pdf-searchable-ocr@7524581185230a248a246acbd3fcd9fbaf190fd5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jasminmistry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
package-publish.yml@7524581185230a248a246acbd3fcd9fbaf190fd5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pdf_searchable_ocr-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pdf_searchable_ocr-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cb5b709155b89348590e444f8232fa429767ab94104528d97122da7a01753f1
|
|
| MD5 |
030b392f2befd0fa71336ae8326a9016
|
|
| BLAKE2b-256 |
0bf7294005d2fa843219f2f57fb19db6d520d6e413917caa2912f874441bb222
|
Provenance
The following attestation bundles were made for pdf_searchable_ocr-0.1.1-py3-none-any.whl:
Publisher:
package-publish.yml on jasminmistry/pdf-searchable-ocr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_searchable_ocr-0.1.1-py3-none-any.whl -
Subject digest:
5cb5b709155b89348590e444f8232fa429767ab94104528d97122da7a01753f1 - Sigstore transparency entry: 597490107
- Sigstore integration time:
-
Permalink:
jasminmistry/pdf-searchable-ocr@7524581185230a248a246acbd3fcd9fbaf190fd5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jasminmistry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
package-publish.yml@7524581185230a248a246acbd3fcd9fbaf190fd5 -
Trigger Event:
push
-
Statement type: