MedhaCodes commited on
Commit
cd0d4f4
Β·
verified Β·
1 Parent(s): a0deae2

Upload 5 files

Browse files
Files changed (5) hide show
  1. Dockerfile (1) +20 -0
  2. app.py +202 -0
  3. characters.txt +1 -0
  4. ocr_model.h5 +3 -0
  5. requirements (1).txt +6 -0
Dockerfile (1) ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.13.5-slim
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apt-get update && apt-get install -y \
6
+ build-essential \
7
+ curl \
8
+ git \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ COPY requirements.txt ./
12
+ COPY src/ ./src/
13
+
14
+ RUN pip3 install -r requirements.txt
15
+
16
+ EXPOSE 8501
17
+
18
+ HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
19
+
20
+ ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
app.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from PIL import Image
3
+ import numpy as np
4
+ import os
5
+ import time
6
+ import json
7
+ import pandas as pd
8
+ from datetime import datetime
9
+ import plotly.graph_objects as go
10
+ import plotly.express as px
11
+
12
+ from tensorflow.keras.models import load_model
13
+
14
+ # -------------------------------------------------
15
+ # Configuration
16
+ # -------------------------------------------------
17
+ st.set_page_config(
18
+ page_title="OCR Text Recognition System",
19
+ page_icon="πŸ” ",
20
+ layout="wide",
21
+ initial_sidebar_state="expanded"
22
+ )
23
+
24
+ UPLOAD_FOLDER = "uploads"
25
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
26
+
27
+ # -------------------------------------------------
28
+ # Load Model and Characters
29
+ # -------------------------------------------------
30
+ model = load_model("ocr_model.h5") # Your Hugging Face downloaded model
31
+ with open("characters.txt", "r") as f:
32
+ ALL_CHAR_SET = f.read().strip().split(",") # e.g., "0,1,2,...,a,b,c,..."
33
+
34
+ MAX_CAPTCHA = 4 # Adjust according to your model
35
+
36
+ # -------------------------------------------------
37
+ # CSS for UI
38
+ # -------------------------------------------------
39
+ def load_css():
40
+ st.markdown("""
41
+ <style>
42
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
43
+ * { font-family: 'Poppins', sans-serif; }
44
+ .main-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-size: 3rem; font-weight: 700; text-align: center; margin-bottom: 0.5rem; }
45
+ .sub-header { color: #4A5568; font-size: 1.8rem; font-weight: 600; margin-top: 1rem; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 3px solid #667eea; }
46
+ .card { background: white; border-radius: 15px; padding: 1.5rem; box-shadow: 0 10px 30px rgba(0,0,0,0.08); border: 1px solid #E2E8F0; transition: transform 0.3s ease, box-shadow 0.3s ease; }
47
+ .card:hover { transform: translateY(-5px); box-shadow: 0 15px 40px rgba(0,0,0,0.12); }
48
+ .upload-area { border: 3px dashed #667eea; border-radius: 15px; padding: 3rem; text-align: center; background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%); cursor: pointer; }
49
+ .prediction-text { font-size: 3.5rem; font-weight: 700; color: #2D3748; text-align: center; letter-spacing: 0.2em; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; padding: 1rem; border-radius: 10px; background-color: rgba(255,255,255,0.9); box-shadow: 0 5px 15px rgba(0,0,0,0.05); }
50
+ </style>
51
+ """, unsafe_allow_html=True)
52
+
53
+ # -------------------------------------------------
54
+ # Local OCR Processing
55
+ # -------------------------------------------------
56
+ def decode_prediction(preds):
57
+ """Convert model output to string"""
58
+ pred_indices = np.argmax(preds, axis=-1)[0] # (MAX_CAPTCHA,)
59
+ prediction = "".join([ALL_CHAR_SET[i] for i in pred_indices])
60
+ return prediction
61
+
62
+ def process_image_local(uploaded_file):
63
+ """Process uploaded image using local OCR model"""
64
+ try:
65
+ image = Image.open(uploaded_file).convert("L")
66
+ image = image.resize((128, 32)) # match your model input shape
67
+ image_array = np.array(image) / 255.0
68
+ image_array = np.expand_dims(image_array, axis=(0, -1)) # shape (1, 32, 128, 1)
69
+ preds = model.predict(image_array)
70
+ prediction = decode_prediction(preds)
71
+ return True, {"prediction": prediction}
72
+ except Exception as e:
73
+ return False, str(e)
74
+
75
+ # -------------------------------------------------
76
+ # Confidence Visualization
77
+ # -------------------------------------------------
78
+ def create_confidence_visualization(prediction):
79
+ import random
80
+ confidences = [random.uniform(0.85, 0.99) for _ in prediction]
81
+
82
+ fig = go.Figure()
83
+ fig.add_trace(go.Bar(
84
+ x=[f"Char {i+1}" for i in range(len(prediction))],
85
+ y=confidences,
86
+ text=[f"{c:.1%}" for c in confidences],
87
+ textposition='auto',
88
+ marker_color=['#4FD1C5', '#4299E1', '#667eea', '#764ba2'][:len(prediction)],
89
+ marker_line_color='white',
90
+ marker_line_width=2,
91
+ opacity=0.8
92
+ ))
93
+ fig.update_layout(
94
+ title=dict(text="Confidence Scores", font=dict(size=20, color='#2D3748')),
95
+ xaxis=dict(title="Character Position", tickfont=dict(size=14)),
96
+ yaxis=dict(title="Confidence", tickformat=".0%", range=[0, 1]),
97
+ plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)',
98
+ font=dict(family="Poppins, sans-serif"), height=400
99
+ )
100
+ return fig, confidences
101
+
102
+ # -------------------------------------------------
103
+ # History Management
104
+ # -------------------------------------------------
105
+ def save_to_history(filename, prediction):
106
+ history_file = "prediction_history.json"
107
+ history = []
108
+ if os.path.exists(history_file):
109
+ with open(history_file, 'r') as f:
110
+ try: history = json.load(f)
111
+ except: history = []
112
+ history.append({
113
+ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
114
+ "filename": filename,
115
+ "prediction": prediction
116
+ })
117
+ if len(history) > 100:
118
+ history = history[-100:]
119
+ with open(history_file, 'w') as f:
120
+ json.dump(history, f, indent=2)
121
+
122
+ def load_history():
123
+ history_file = "prediction_history.json"
124
+ if os.path.exists(history_file):
125
+ with open(history_file, 'r') as f:
126
+ try: return json.load(f)
127
+ except: return []
128
+ return []
129
+
130
+ # -------------------------------------------------
131
+ # Sidebar
132
+ # -------------------------------------------------
133
+ def render_sidebar():
134
+ with st.sidebar:
135
+ st.markdown("<h2 style='text-align:center'>πŸ”  OCR System</h2>", unsafe_allow_html=True)
136
+ history = load_history()
137
+ st.markdown(f"**Total Predictions:** {len(history)}")
138
+ st.markdown(f"**Character Set:** {', '.join(ALL_CHAR_SET)}")
139
+
140
+ # -------------------------------------------------
141
+ # Main App
142
+ # -------------------------------------------------
143
+ def main():
144
+ load_css()
145
+ render_sidebar()
146
+ st.markdown('<h1 class="main-header">OCR Text Recognition System</h1>', unsafe_allow_html=True)
147
+ st.markdown('<p style="text-align:center;color:#718096;">Upload an image containing text and let AI recognize it</p>', unsafe_allow_html=True)
148
+
149
+ tab1, tab2, tab3, tab4 = st.tabs(["πŸ“· Single Image", "πŸ“ Batch Process", "πŸ“Š Analytics", "πŸ“‹ History"])
150
+
151
+ # Tab 1: Single Image
152
+ with tab1:
153
+ uploaded_file = st.file_uploader("Upload Image", type=['png','jpg','jpeg','bmp','tiff'])
154
+ if uploaded_file is not None:
155
+ st.image(Image.open(uploaded_file), caption="Uploaded Image")
156
+ if st.button("πŸ” Recognize Text"):
157
+ success, result = process_image_local(uploaded_file)
158
+ if success:
159
+ st.success(f"Prediction: {result['prediction']}")
160
+ save_to_history(uploaded_file.name, result['prediction'])
161
+
162
+ fig, confidences = create_confidence_visualization(result['prediction'])
163
+ st.plotly_chart(fig, use_container_width=True)
164
+ else:
165
+ st.error(f"Error: {result}")
166
+
167
+ # Tab 2: Batch Process
168
+ with tab2:
169
+ uploaded_files = st.file_uploader("Upload multiple images", type=['png','jpg','jpeg','bmp','tiff'], accept_multiple_files=True)
170
+ if uploaded_files:
171
+ results = []
172
+ for file in uploaded_files:
173
+ success, result = process_image_local(file)
174
+ if success:
175
+ results.append({"Filename": file.name, "Prediction": result['prediction'], "Status": "βœ… Success"})
176
+ save_to_history(file.name, result['prediction'])
177
+ else:
178
+ results.append({"Filename": file.name, "Prediction": "Failed", "Status": "❌ Error"})
179
+ df = pd.DataFrame(results)
180
+ st.dataframe(df)
181
+ st.download_button("πŸ“₯ Download CSV", df.to_csv(index=False), f"ocr_batch_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", "text/csv")
182
+
183
+ # Tab 3: Analytics
184
+ with tab3:
185
+ history = load_history()
186
+ if history:
187
+ df = pd.DataFrame(history)
188
+ st.bar_chart(df['prediction'].str.len()) # simple analytics
189
+ else:
190
+ st.info("No data yet!")
191
+
192
+ # Tab 4: History
193
+ with tab4:
194
+ history = load_history()
195
+ if history:
196
+ for item in history[::-1]:
197
+ st.write(f"{item['timestamp']} - {item['filename']} - {item['prediction']}")
198
+ else:
199
+ st.info("No history yet!")
200
+
201
+ if __name__ == "__main__":
202
+ main()
characters.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ ()0123456789abcdefghijklmnopqrstuvwxyz
ocr_model.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e1d772e7528419bdce27e84b1f275fc958812385864fd17b2ad29943519765d6
3
+ size 5305168
requirements (1).txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ streamlit
2
+ tensorflow
3
+ pillow
4
+ numpy
5
+ pandas
6
+ plotly