smart-ocr
Skill433 starsChanged 10 months agoMITView on GitHub
>
- Installs packages
In this repository137 other files it gives its agents.
- .cursor/rules/project-rules.mdcCursor rule
- academic-searchSkill
- ads-copywriterSkill
- ai-agent-builderSkill
- airtable-automationSkill
- ai-slidesSkill
- Amazon SellerSkill
- Apple Shortcuts IntegrationSkill
- Applicant ScreeningSkill
- Asana AutomationSkill
- batch-convertSkill
- batch-processorSkill
- Brand Guidelines GeneratorSkill
- Browser AutomationSkill
- calendar-automationSkill
- Changelog GeneratorSkill
- chart-designerSkill
- Chat with PDFSkill
- ClickUp AutomationSkill
- company-researchSkill
- competitive-analysisSkill
- Content Research WriterSkill
- contract-reviewSkill
- contract-templateSkill
- cover-letterSkill
- crm-automationSkill
- crypto-reportSkill
- customer-successSkill
- cv-builderSkill
- data-analysisSkill
- Database SyncSkill
- data-extractorSkill
- data-pipelineSkill
- dcf-valuationSkill
- deep-researchSkill
- devops-automationSkill
- dev-slidesSkill
- diagram-creatorSkill
- discord-botSkill
- doc-parserSkill
- doc-pipelineSkill
- DocuSign AutomationSkill
- docx-manipulationSkill
- Email ClassifierSkill
- email-drafterSkill
- email-marketingSkill
- ETL PipelineSkill
- excel-automationSkill
- expense-reportSkill
- Expense TrackerSkill
- Facebook/Meta AdsSkill
- File OrganizerSkill
- financial-modelingSkill
- form-builderSkill
- gmail-workflowsSkill
- google-ads-managerSkill
- Home Assistant AutomationSkill
- hr-automationSkill
- html-slidesSkill
- html-to-pptSkill
- The first 60 shown.
The file
Files
Smart OCR Skill
Overview
This skill enables intelligent text extraction from images and scanned documents using PaddleOCR - a leading OCR engine supporting 100+ languages. Extract text from photos, screenshots, scanned PDFs, and handwritten documents with high accuracy.
How to Use
- Provide the image or scanned document
- Optionally specify language(s) to detect
- I'll extract text with position and confidence data
Example prompts:
- "Extract all text from this screenshot"
- "OCR this scanned PDF document"
- "Read the text from this business card photo"
- "Extract Chinese and English text from this image"
Domain Knowledge
PaddleOCR Fundamentals
from paddleocr import PaddleOCR
# Initialize OCR engine
ocr = PaddleOCR(use_angle_cls=True, lang='en')
# Run OCR on image
result = ocr.ocr('image.png', cls=True)
# Result structure: [[box, (text, confidence)], ...]
for line in result[0]:
box = line[0] # [[x1,y1], [x2,y2], [x3,y3], [x4,y4]]
text = line[1][0] # Extracted text
conf = line[1][1] # Confidence score
print(f"{text} ({conf:.2f})")Supported Languages
# Common language codes
languages = {
'en': 'English',
'ch': 'Chinese (Simplified)',
'cht': 'Chinese (Traditional)',
'japan': 'Japanese',
'korean': 'Korean',
'french': 'French',
'german': 'German',
'spanish': 'Spanish',
'russian': 'Russian',
'arabic': 'Arabic',
'hindi': 'Hindi',
'vi': 'Vietnamese',
'th': 'Thai',
# ... 100+ languages supported
}
# Use specific language
ocr = PaddleOCR(lang='ch') # Chinese
ocr = PaddleOCR(lang='japan') # Japanese
ocr = PaddleOCR(lang='multilingual') # Auto-detectConfiguration Options
from paddleocr import PaddleOCR
ocr = PaddleOCR(
# Detection settings
det_model_dir=None, # Custom detection model
det_limit_side_len=960, # Max side length for detection
det_db_thresh=0.3, # Binarization threshold
det_db_box_thresh=0.5, # Box score threshold
# Recognition settings
rec_model_dir=None, # Custom recognition model
rec_char_dict_path=None, # Custom character dictionary
# Angle classification
use_angle_cls=True, # Enable angle classification
cls_model_dir=None, # Custom classification model
# Language
lang='en', # Language code
# Performance
use_gpu=True, # Use GPU if available
gpu_mem=500, # GPU memory limit (MB)
enable_mkldnn=True, # CPU optimization
# Output
show_log=False, # Suppress logs
)Processing Different Sources
Image Files
# Single image
result = ocr.ocr('image.png')
# Multiple images
images = ['img1.png', 'img2.png', 'img3.png']
for img in images:
result = ocr.ocr(img)
process_result(result)PDF Files (Scanned)
from pdf2image import convert_from_path
def ocr_pdf(pdf_path):
"""OCR a scanned PDF."""
# Convert PDF pages to images
images = convert_from_path(pdf_path)
all_text = []
for i, img in enumerate(images):
# Save temp image
temp_path = f'temp_page_{i}.png'
img.save(temp_path)
# OCR the image
result = ocr.ocr(temp_path)
# Extract text
page_text = '\n'.join([line[1][0] for line in result[0]])
all_text.append(f"--- Page {i+1} ---\n{page_text}")
os.remove(temp_path)
return '\n\n'.join(all_text)URLs and Bytes
import requests
from io import BytesIO
# From URL
response = requests.get('https://example.com/image.png')
result = ocr.ocr(BytesIO(response.content))
# From bytes
with open('image.png', 'rb') as f:
img_bytes = f.read()
result = ocr.ocr(BytesIO(img_bytes))Result Processing
def process_ocr_result(result):
"""Process OCR result into structured data."""
lines = []
for line in result[0]:
box = line[0]
text = line[1][0]
confidence = line[1][1]
# Calculate bounding box
x_coords = [p[0] for p in box]
y_coords = [p[1] for p in box]
lines.append({
'text': text,
'confidence': confidence,
'bbox': {
'left': min(x_coords),
'top': min(y_coords),
'right': max(x_coords),
'bottom': max(y_coords),
},
'raw_box': box
})
return lines
# Sort by position (top to bottom, left to right)
def sort_by_position(lines):
return sorted(lines, key=lambda x: (x['bbox']['top'], x['bbox']['left']))Text Layout Reconstruction
def reconstruct_layout(result, line_threshold=10):
"""Reconstruct text layout from OCR results."""
lines = process_ocr_result(result)
lines = sort_by_position(lines)
# Group into logical lines
text_lines = []
current_line = []
current_y = None
for line in lines:
y = line['bbox']['top']
if current_y is None or abs(y - current_y) < line_threshold:
current_line.append(line)
current_y = y
else:
# New line
text_lines.append(' '.join([l['text'] for l in current_line]))
current_line = [line]
current_y = y
# Add last line
if current_line:
text_lines.append(' '.join([l['text'] for l in current_line]))
return '\n'.join(text_lines)Best Practices
- Preprocess Images: Improve quality before OCR
- Choose Correct Language: Specify language for better accuracy
- Handle Multi-column: Process columns separately
- Filter Low Confidence: Skip results below threshold
- Batch Processing: Process multiple images efficiently
Common Patterns
Image Preprocessing
from PIL import Image, ImageEnhance, ImageFilter
def preprocess_image(image_path):
"""Preprocess image for better OCR."""
img = Image.open(image_path)
# Convert to grayscale
img = img.convert('L')
# Enhance contrast
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
# Sharpen
img = img.filter(ImageFilter.SHARPEN)
# Save preprocessed
preprocessed_path = 'preprocessed.png'
img.save(preprocessed_path)
return preprocessed_pathBatch OCR with Progress
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor
def batch_ocr(image_paths, max_workers=4):
"""OCR multiple images in parallel."""
results = {}
def process_single(img_path):
result = ocr.ocr(img_path)
return img_path, result
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(process_single, p) for p in image_paths]
for future in tqdm(futures, desc="Processing OCR"):
path, result = future.result()
results[path] = result
return resultsExamples
Example 1: Business Card Reader
from paddleocr import PaddleOCR
import re
def read_business_card(image_path):
"""Extract contact info from business card."""
ocr = PaddleOCR(use_angle_cls=True, lang='en')
result = ocr.ocr(image_path)
# Extract all text
all_text = []
for line in result[0]:
all_text.append(line[1][0])
full_text = '\n'.join(all_text)
# Parse contact info
contact = {
'name': None,
'email': None,
'phone': None,
'company': None,
'title': None,
'raw_text': full_text
}
# Email pattern
email_match = re.search(r'[\w\.-]+@[\w\.-]+\.\w+', full_text)
if email_match:
contact['email'] = email_match.group()
# Phone pattern
phone_match = re.search(r'[\+\d][\d\s\-\(\)]{8,}', full_text)
if phone_match:
contact['phone'] = phone_match.group().strip()
# Name is usually the largest/first text
if all_text:
contact['name'] = all_text[0]
return contact
card_info = read_business_card('business_card.jpg')
print(f"Name: {card_info['name']}")
print(f"Email: {card_info['email']}")
print(f"Phone: {card_info['phone']}")Example 2: Receipt Scanner
from paddleocr import PaddleOCR
import re
def scan_receipt(image_path):
"""Extract items and total from receipt."""
ocr = PaddleOCR(use_angle_cls=True, lang='en')
result = ocr.ocr(image_path)
lines = []
for line in result[0]:
text = line[1][0]
y_pos = line[0][0][1]
lines.append({'text': text, 'y': y_pos})
# Sort by vertical position
lines.sort(key=lambda x: x['y'])
receipt = {
'items': [],
'subtotal': None,
'tax': None,
'total': None
}
for line in lines:
text = line['text']
# Look for total
if 'total' in text.lower():
amount = re.search(r'\$?([\d,]+\.?\d*)', text)
if amount:
if 'sub' in text.lower():
receipt['subtotal'] = float(amount.group(1).replace(',', ''))
else:
receipt['total'] = float(amount.group(1).replace(',', ''))
# Look for tax
elif 'tax' in text.lower():
amount = re.search(r'\$?([\d,]+\.?\d*)', text)
if amount:
receipt['tax'] = float(amount.group(1).replace(',', ''))
# Look for items (line with price)
else:
item_match = re.search(r'(.+?)\s+\$?([\d,]+\.?\d+)$', text)
if item_match:
receipt['items'].append({
'name': item_match.group(1).strip(),
'price': float(item_match.group(2).replace(',', ''))
})
return receipt
receipt_data = scan_receipt('receipt.jpg')
print(f"Items: {len(receipt_data['items'])}")
print(f"Total: ${receipt_data['total']}")Example 3: Multi-language Document
from paddleocr import PaddleOCR
def ocr_multilingual(image_path, languages=['en', 'ch']):
"""OCR document with multiple languages."""
all_results = {}
for lang in languages:
ocr = PaddleOCR(use_angle_cls=True, lang=lang)
result = ocr.ocr(image_path)
texts = []
for line in result[0]:
texts.append({
'text': line[1][0],
'confidence': line[1][1]
})
all_results[lang] = texts
# Merge results, keeping highest confidence
merged = {}
for lang, texts in all_results.items():
for item in texts:
text = item['text']
conf = item['confidence']
if text not in merged or merged[text]['confidence'] < conf:
merged[text] = {'confidence': conf, 'language': lang}
return merged
result = ocr_multilingual('bilingual_document.png')
for text, info in result.items():
print(f"[{info['language']}] {text} ({info['confidence']:.2f})")Limitations
- Handwritten text accuracy varies
- Very small text may not be detected
- Complex backgrounds reduce accuracy
- Rotated text needs angle classification
- GPU recommended for best performance
Installation
# CPU version
pip install paddlepaddle paddleocr
# GPU version (CUDA 11.x)
pip install paddlepaddle-gpu paddleocr
# Additional dependencies
pip install pdf2image PillowResources
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

