hoololi commited on
Commit
4cdaaea
·
verified ·
1 Parent(s): 5855ebc

Delete image_processing.py

Browse files
Files changed (1) hide show
  1. image_processing.py +0 -251
image_processing.py DELETED
@@ -1,251 +0,0 @@
1
- # ==========================================
2
- # image_processing.py - Calcul OCR v3.0 CLEAN
3
- # ==========================================
4
-
5
- """
6
- Module de traitement d'images pour calculs mathématiques - EasyOCR UNIQUEMENT
7
- """
8
-
9
- from PIL import Image, ImageEnhance
10
- import numpy as np
11
- import base64
12
- from io import BytesIO
13
- import gc
14
- import os
15
- import time
16
-
17
- # Variables globales pour OCR EasyOCR uniquement
18
- easyocr_reader = None
19
-
20
- def init_ocr_model() -> bool:
21
- """Initialise EasyOCR (rapide et efficace sur CPU)"""
22
- global easyocr_reader
23
-
24
- try:
25
- print("🔄 Chargement EasyOCR (optimisé CPU)...")
26
- import easyocr
27
- easyocr_reader = easyocr.Reader(['en'], gpu=False) # Force CPU pour compatibilité
28
- print("✅ EasyOCR prêt !")
29
- return True
30
-
31
- except Exception as e:
32
- print(f"❌ Erreur lors du chargement EasyOCR: {e}")
33
- return False
34
-
35
- def create_white_canvas(width: int = 300, height: int = 300) -> Image.Image:
36
- """Crée un canvas blanc pour le dessin de calculs"""
37
- return Image.new('RGB', (width, height), 'white')
38
-
39
- def log_memory_usage(context: str = "") -> None:
40
- """Log l'usage mémoire actuel"""
41
- try:
42
- import psutil
43
- process = psutil.Process(os.getpid())
44
- memory_mb = process.memory_info().rss / 1024 / 1024
45
- print(f"🔍 Mémoire {context}: {memory_mb:.1f}MB")
46
- except:
47
- pass
48
-
49
- def cleanup_memory() -> None:
50
- """Force le nettoyage mémoire"""
51
- gc.collect()
52
-
53
- def optimize_image_for_ocr(image_dict: dict | np.ndarray | Image.Image | None) -> Image.Image | None:
54
- """Optimisation image pour reconnaissance de nombres avec EasyOCR"""
55
- if image_dict is None:
56
- return None
57
-
58
- try:
59
- # Gérer les formats Gradio
60
- if isinstance(image_dict, dict):
61
- if 'composite' in image_dict and image_dict['composite'] is not None:
62
- image = image_dict['composite']
63
- elif 'background' in image_dict and image_dict['background'] is not None:
64
- image = image_dict['background']
65
- else:
66
- return None
67
- elif isinstance(image_dict, np.ndarray):
68
- image = image_dict
69
- elif isinstance(image_dict, Image.Image):
70
- image = image_dict
71
- else:
72
- return None
73
-
74
- # Conversion
75
- if isinstance(image, np.ndarray):
76
- pil_image = Image.fromarray(image).convert('RGB')
77
- else:
78
- pil_image = image.convert('RGB')
79
-
80
- # Redimensionner si nécessaire pour optimiser OCR
81
- max_size = 300
82
- if pil_image.size[0] > max_size or pil_image.size[1] > max_size:
83
- pil_image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
84
-
85
- return pil_image
86
-
87
- except Exception:
88
- return None
89
-
90
- def prepare_image_for_dataset(image: Image.Image, max_size: tuple[int, int] = (100, 100), quality: int = 60) -> dict[str, str | int | float | tuple] | None:
91
- """Prépare image pour dataset calcul OCR"""
92
- try:
93
- if image is None:
94
- return None
95
-
96
- # Copier et redimensionner
97
- dataset_image = image.copy()
98
- dataset_image.thumbnail(max_size, Image.Resampling.LANCZOS)
99
- compressed_size = dataset_image.size
100
-
101
- # Convertir en base64
102
- buffer = BytesIO()
103
- dataset_image.save(buffer, format='PNG', optimize=True, quality=quality)
104
-
105
- buffer_data = buffer.getvalue()
106
- image_base64 = base64.b64encode(buffer_data).decode()
107
- file_size_kb = len(image_base64) / 1024
108
-
109
- # Structure propre pour dataset
110
- result = {
111
- "image_base64": image_base64,
112
- "compressed_size": compressed_size,
113
- "file_size_kb": round(file_size_kb, 1),
114
- "format": "PNG",
115
- "quality": quality
116
- }
117
-
118
- # Nettoyage
119
- dataset_image.close()
120
- buffer.close()
121
-
122
- return result
123
-
124
- except Exception as e:
125
- print(f"❌ Erreur préparation image: {e}")
126
- return None
127
-
128
- def recognize_number_fast_with_image(image_dict: dict | np.ndarray | Image.Image | None) -> tuple[str, Image.Image | None, dict | None]:
129
- """OCR avec EasyOCR uniquement (rapide et efficace)"""
130
- if image_dict is None:
131
- print(" ❌ Image manquante")
132
- return "0", None, None
133
-
134
- if easyocr_reader is None:
135
- print(" ❌ EasyOCR non initialisé")
136
- return "0", None, None
137
-
138
- try:
139
- print(" 🔄 Début OCR EasyOCR...")
140
- start_time = time.time()
141
-
142
- # Optimiser image
143
- print(" 📐 Optimisation image...")
144
- opt_start = time.time()
145
- optimized_image = optimize_image_for_ocr(image_dict)
146
- if optimized_image is None:
147
- print(" ❌ Échec optimisation image")
148
- return "0", None, None
149
- print(f" ✅ Image optimisée en {time.time() - opt_start:.1f}s")
150
-
151
- # EasyOCR - simple et rapide
152
- print(" ⚡ Lancement EasyOCR...")
153
- easy_start = time.time()
154
-
155
- # Convertir PIL vers numpy pour EasyOCR
156
- img_array = np.array(optimized_image)
157
- results = easyocr_reader.readtext(img_array, detail=0, paragraph=False)
158
-
159
- if results:
160
- # Extraire les chiffres de tous les résultats
161
- all_text = ' '.join(str(r) for r in results)
162
- cleaned_result = ''.join(filter(str.isdigit, all_text))
163
-
164
- # Validation longueur
165
- if cleaned_result and len(cleaned_result) <= 4:
166
- final_result = cleaned_result
167
- else:
168
- # Si trop long, prendre les premiers chiffres
169
- final_result = cleaned_result[:4] if cleaned_result else "0"
170
- else:
171
- final_result = "0"
172
-
173
- print(f" ✅ EasyOCR en {time.time() - easy_start:.1f}s → '{final_result}'")
174
-
175
- # Préparer pour dataset
176
- print(" 📦 Préparation dataset...")
177
- dataset_start = time.time()
178
- dataset_image_data = prepare_image_for_dataset(optimized_image)
179
- print(f" ✅ Dataset prep en {time.time() - dataset_start:.1f}s")
180
-
181
- total_time = time.time() - start_time
182
- print(f" 🏁 OCR total: {total_time:.1f}s")
183
-
184
- return final_result, optimized_image, dataset_image_data
185
-
186
- except Exception as e:
187
- print(f"❌ Erreur OCR EasyOCR: {e}")
188
- import traceback
189
- traceback.print_exc()
190
- return "0", None, None
191
-
192
- def recognize_number_fast(image_dict: dict | np.ndarray | Image.Image | None) -> tuple[str, Image.Image | None]:
193
- """Version rapide standard pour calculs avec EasyOCR"""
194
- result, optimized_image, _ = recognize_number_fast_with_image(image_dict)
195
- return result, optimized_image
196
-
197
- def recognize_number(image_dict: dict | np.ndarray | Image.Image | None) -> str:
198
- """Interface standard pour reconnaissance de calculs avec EasyOCR"""
199
- result, _ = recognize_number_fast(image_dict)
200
- return result
201
-
202
- def create_thumbnail_fast(optimized_image: Image.Image | None, size: tuple[int, int] = (40, 40)) -> str:
203
- """Création miniature rapide pour calculs"""
204
- try:
205
- if optimized_image is None:
206
- return "📝"
207
-
208
- thumbnail = optimized_image.copy()
209
- thumbnail.thumbnail(size, Image.Resampling.LANCZOS)
210
-
211
- buffer = BytesIO()
212
- thumbnail.save(buffer, format='PNG', optimize=True, quality=70)
213
- img_str = base64.b64encode(buffer.getvalue()).decode()
214
-
215
- thumbnail.close()
216
- buffer.close()
217
-
218
- return f'<img src="data:image/png;base64,{img_str}" width="{size[0]}" height="{size[1]}" style="border: 1px solid #ccc; border-radius: 3px;" alt="Réponse calcul">'
219
-
220
- except Exception:
221
- return "📝"
222
-
223
- # Fonction utilitaire pour fine-tuning calculs
224
- def decode_image_from_dataset(base64_string: str) -> Image.Image | None:
225
- """Décode une image depuis le dataset pour fine-tuning calculs avec EasyOCR"""
226
- try:
227
- image_bytes = base64.b64decode(base64_string)
228
- image = Image.open(BytesIO(image_bytes))
229
- return image
230
- except Exception as e:
231
- print(f"Erreur décodage calcul: {e}")
232
- return None
233
-
234
- # Fonctions d'analyse pour différents types de calculs
235
- def analyze_calculation_complexity(operand_a: int, operand_b: int, operation: str) -> dict:
236
- """Analyse la complexité d'un calcul pour le dataset"""
237
- complexity_score = 0
238
-
239
- if operation == "×":
240
- complexity_score = max(operand_a, operand_b)
241
- elif operation == "+":
242
- complexity_score = (operand_a + operand_b) / 20
243
- elif operation == "-":
244
- complexity_score = max(operand_a, operand_b) / 10
245
- elif operation == "÷":
246
- complexity_score = operand_a / 10
247
-
248
- return {
249
- "complexity_score": round(complexity_score, 2),
250
- "difficulty_category": "easy" if complexity_score < 5 else "medium" if complexity_score < 10 else "hard"
251
- }