-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathapp.py
More file actions
114 lines (95 loc) · 3.25 KB
/
app.py
File metadata and controls
114 lines (95 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from flask import Flask, request, jsonify, render_template
from flask_cors import CORS
import numpy as np
import io
import cv2
import easyocr
import time
import logging
import os
# -------------------------------
# Flask App Setup
# -------------------------------
app = Flask(__name__)
CORS(app)
# Logging Configuration
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] - %(message)s"
)
# -------------------------------
# EasyOCR Reader Initialization
# -------------------------------
try:
reader = easyocr.Reader(['en'], gpu=True)
logging.info("✅ EasyOCR initialized using GPU.")
except Exception as e:
reader = easyocr.Reader(['en'], gpu=False)
logging.warning(f"⚠️ GPU not available, falling back to CPU. Reason: {e}")
# -------------------------------
# Helper Function: Preprocessing
# -------------------------------
def preprocess_image(image_bytes: bytes) -> bytes:
"""
Enhance the image for better OCR results.
- Converts to grayscale
- Applies CLAHE for contrast enhancement
Returns processed image bytes.
"""
nparr = np.frombuffer(image_bytes, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
if img is None:
raise ValueError("Invalid image file")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Contrast enhancement
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
enhanced_gray = clahe.apply(gray)
_, buffer = cv2.imencode('.png', enhanced_gray)
return buffer.tobytes()
# -------------------------------
# Routes
# -------------------------------
@app.route('/')
def home():
"""Render the homepage."""
return render_template('index.html')
@app.route('/api/ocr', methods=['POST'])
def ocr_endpoint():
"""
Endpoint: /api/ocr
Accepts: image (multipart/form-data)
Returns: extracted text in JSON
"""
start_time = time.time()
if 'image' not in request.files:
return jsonify({'error': 'No file part named "image" found.'}), 400
file = request.files['image']
if not file or file.filename == '':
return jsonify({'error': 'No file selected.'}), 400
# Validate file type
allowed_extensions = {'png', 'jpg', 'jpeg', 'bmp', 'tiff'}
ext = file.filename.rsplit('.', 1)[-1].lower()
if ext not in allowed_extensions:
return jsonify({'error': 'Unsupported file type.'}), 400
try:
image_bytes = file.read()
processed_bytes = preprocess_image(image_bytes)
# OCR Extraction
results = reader.readtext(processed_bytes)
extracted_text = "\n".join([res[1] for res in results]).strip()
response_time = round(time.time() - start_time, 2)
logging.info(f"OCR processed in {response_time}s")
return jsonify({
'text': extracted_text,
'processing_time': f"{response_time}s"
}), 200
except Exception as e:
logging.error(f"OCR Processing Error: {e}")
return jsonify({'error': f"OCR failed: {str(e)}"}), 500
# -------------------------------
# Main Entrypoint
# -------------------------------
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5000))
logging.info(f"🚀 Starting Flask server on port {port}...")
app.run(debug=True, host='0.0.0.0', port=port)