feat(generate-song): add ACE-Step download script, remove legacy effi-ocr
- Add download-ace-step-full.sh script for easier model downloads - Remove effi-ocr (migrated to effi-kreuzberg for OCR functionality) - Generate Song v0.5.4 now fully functional with JK-AceStep-Nodes
This commit is contained in:
Executable
+72
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
# Script de téléchargement des modèles ACE-Step 1.5 COMPLETS
|
||||
# À lancer sur Folzo Corp
|
||||
|
||||
set -e
|
||||
|
||||
BASE_DIR="/home/folzo/Documents/OpenCode/Projets/Effi/comfyui/models"
|
||||
|
||||
echo "🎵 ACE-Step 1.5 - Téléchargement COMPLET des modèles"
|
||||
echo "===================================================="
|
||||
echo ""
|
||||
|
||||
# 1. VAE
|
||||
echo "📦 1/4 - Téléchargement du VAE..."
|
||||
mkdir -p "$BASE_DIR/vae"
|
||||
cd "$BASE_DIR/vae"
|
||||
if [ ! -f "ace_1.5_vae.safetensors" ]; then
|
||||
wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/vae/diffusion_pytorch_model.safetensors" -O "ace_1.5_vae.safetensors"
|
||||
echo "✅ VAE téléchargé"
|
||||
else
|
||||
echo "✅ VAE déjà présent"
|
||||
fi
|
||||
ls -lh "ace_1.5_vae.safetensors"
|
||||
|
||||
echo ""
|
||||
|
||||
# 2. Diffusion Model
|
||||
echo "📦 2/4 - Téléchargement du modèle de diffusion..."
|
||||
mkdir -p "$BASE_DIR/diffusion_models"
|
||||
cd "$BASE_DIR/diffusion_models"
|
||||
if [ ! -f "acestep_v1.5_turbo.safetensors" ]; then
|
||||
wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/acestep-v15-turbo/model.safetensors" -O "acestep_v1.5_turbo.safetensors"
|
||||
echo "✅ Diffusion model téléchargé"
|
||||
else
|
||||
echo "✅ Diffusion model déjà présent"
|
||||
fi
|
||||
ls -lh "acestep_v1.5_turbo.safetensors"
|
||||
|
||||
echo ""
|
||||
|
||||
# 3. Text Encoder 0.6B
|
||||
echo "📦 3/4 - Téléchargement du text encoder 0.6B..."
|
||||
mkdir -p "$BASE_DIR/text_encoders"
|
||||
cd "$BASE_DIR/text_encoders"
|
||||
if [ ! -f "qwen_0.6b_ace15.safetensors" ]; then
|
||||
wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/acestep-5Hz-lm-0.6B/model.safetensors" -O "qwen_0.6b_ace15.safetensors"
|
||||
echo "✅ Text encoder 0.6B téléchargé"
|
||||
else
|
||||
echo "✅ Text encoder 0.6B déjà présent"
|
||||
fi
|
||||
ls -lh "qwen_0.6b_ace15.safetensors"
|
||||
|
||||
echo ""
|
||||
|
||||
# 4. Text Encoder 4B
|
||||
echo "📦 4/4 - Téléchargement du text encoder 4B..."
|
||||
cd "$BASE_DIR/text_encoders"
|
||||
if [ ! -f "qwen_4b_ace15.safetensors" ]; then
|
||||
wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/acestep-5Hz-lm-4B/model.safetensors" -O "qwen_4b_ace15.safetensors"
|
||||
echo "✅ Text encoder 4B téléchargé"
|
||||
else
|
||||
echo "✅ Text encoder 4B déjà présent"
|
||||
fi
|
||||
ls -lh "qwen_4b_ace15.safetensors"
|
||||
|
||||
echo ""
|
||||
echo "===================================================="
|
||||
echo "🎉 Téléchargement terminé !"
|
||||
echo ""
|
||||
echo "Prochaine étape : redémarrer ComfyUI"
|
||||
echo "docker restart comfyui"
|
||||
echo "===================================================="
|
||||
@@ -1,20 +0,0 @@
|
||||
FROM python:3.11-slim
|
||||
# Installer Tesseract et les langues
|
||||
RUN apt-get update && apt-get install -y \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-fra \
|
||||
tesseract-ocr-eng \
|
||||
libtesseract-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
# Créer le répertoire de travail
|
||||
WORKDIR /app
|
||||
# Copier les dépendances
|
||||
COPY requirements.txt .
|
||||
# Installer les dépendances Python
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
# Copier le code
|
||||
COPY main.py .
|
||||
# Exposer le port
|
||||
EXPOSE 8300
|
||||
# Lancer l'application
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8300"]
|
||||
@@ -1,232 +0,0 @@
|
||||
# 📝 Effi-OCR
|
||||
|
||||
Service OCR (Optical Character Recognition) pour Effi. Extrait le texte des images et photos de documents.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Fonctionnalités
|
||||
|
||||
- Extraction de texte à partir d'images (JPEG, PNG, GIF, BMP, TIFF, WebP)
|
||||
- Support multilingue (Français, Anglais, Allemand, Espagnol, Italien)
|
||||
- Prétraitement automatique pour améliorer la qualité
|
||||
- API REST simple et rapide
|
||||
- Intégration OpenWebUI via Tool
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Démarrage rapide
|
||||
|
||||
```bash
|
||||
# Construire et démarrer
|
||||
cd ~/Documents/OpenCode/Projets/Effi/effi-ocr
|
||||
sudo docker compose up -d --build
|
||||
|
||||
# Vérifier le service
|
||||
curl http://localhost:8300/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📡 API Endpoints
|
||||
|
||||
### Health Check
|
||||
```bash
|
||||
GET /health
|
||||
```
|
||||
|
||||
### OCR - Upload fichier
|
||||
```bash
|
||||
POST /ocr
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
Parameters:
|
||||
- file: Image à analyser
|
||||
- lang: Code langue (fra, eng, fra+eng, etc.)
|
||||
- preprocess: true/false (prétraitement auto)
|
||||
```
|
||||
|
||||
Exemple:
|
||||
```bash
|
||||
curl -X POST -F "file=@photo.jpg" -F "lang=fra" http://localhost:8300/ocr
|
||||
```
|
||||
|
||||
### OCR - Base64
|
||||
```bash
|
||||
POST /ocr/base64
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"image_base64": "...",
|
||||
"lang": "fra",
|
||||
"preprocess": true
|
||||
}
|
||||
```
|
||||
|
||||
### Langues disponibles
|
||||
```bash
|
||||
GET /languages
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Variables d'environnement
|
||||
|
||||
| Variable | Défaut | Description |
|
||||
|----------|--------|-------------|
|
||||
| `OCR_URL` | `http://192.168.1.11:8300` | URL du service OCR |
|
||||
|
||||
### Langues supportées
|
||||
|
||||
- `fra` - Français
|
||||
- `eng` - Anglais
|
||||
- `fra+eng` - Bilingue FR+EN
|
||||
- `deu` - Allemand
|
||||
- `spa` - Espagnol
|
||||
- `ita` - Italien
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker
|
||||
|
||||
### Construction
|
||||
```bash
|
||||
sudo docker compose build
|
||||
```
|
||||
|
||||
### Démarrage
|
||||
```bash
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
### Logs
|
||||
```bash
|
||||
sudo docker logs effi-ocr -f
|
||||
```
|
||||
|
||||
### Arrêt
|
||||
```bash
|
||||
sudo docker compose down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Intégration OpenWebUI
|
||||
|
||||
Voir [TOOL-OPENWEBUI.md](TOOL-OPENWEBUI.md) pour la configuration complète du Tool.
|
||||
|
||||
**Résumé rapide:**
|
||||
1. Admin → Tools → Create Tool
|
||||
2. Copier le code Python fourni
|
||||
3. Configurer la variable `OCR_URL`
|
||||
4. Activer le Tool dans les paramètres de conversation
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
### Test de santé
|
||||
```bash
|
||||
curl http://localhost:8300/health
|
||||
```
|
||||
|
||||
### Test OCR simple
|
||||
```bash
|
||||
curl -X POST \
|
||||
-F "file=@/chemin/vers/image.jpg" \
|
||||
-F "lang=fra" \
|
||||
http://localhost:8300/ocr
|
||||
```
|
||||
|
||||
### Test avec prétraitement désactivé
|
||||
```bash
|
||||
curl -X POST \
|
||||
-F "file=@image.png" \
|
||||
-F "lang=eng" \
|
||||
-F "preprocess=false" \
|
||||
http://localhost:8300/ocr
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Performance
|
||||
|
||||
- **Temps de traitement** : ~1-3 secondes par image (dépend de la taille)
|
||||
- **Formats supportés** : JPEG, PNG, GIF, BMP, TIFF, WebP
|
||||
- **Taille max recommandée** : 2048x2048 pixels
|
||||
- **Prétraitement** : Conversion niveaux de gris + contraste (optionnel)
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Dépannage
|
||||
|
||||
### Service ne répond pas
|
||||
```bash
|
||||
# Vérifier si le conteneur tourne
|
||||
sudo docker ps | grep effi-ocr
|
||||
|
||||
# Redémarrer
|
||||
sudo docker restart effi-ocr
|
||||
|
||||
# Voir les logs
|
||||
sudo docker logs effi-ocr
|
||||
```
|
||||
|
||||
### Tesseract non trouvé
|
||||
L'erreur indique que Tesseract n'est pas installé dans le conteneur. Reconstruire:
|
||||
```bash
|
||||
sudo docker compose down
|
||||
sudo docker compose up -d --build
|
||||
```
|
||||
|
||||
### OCR de mauvaise qualité
|
||||
- Utiliser `lang=fra+eng` pour les documents mixtes
|
||||
- S'assurer que l'image est bien éclairée
|
||||
- Vérifier la résolution (300 DPI recommandé pour documents)
|
||||
- Activer le prétraitement (par défaut: true)
|
||||
|
||||
---
|
||||
|
||||
## 📁 Structure
|
||||
|
||||
```
|
||||
effi-ocr/
|
||||
├── main.py # API FastAPI
|
||||
├── Dockerfile # Configuration Docker
|
||||
├── docker-compose.yml # Orchestration
|
||||
├── requirements.txt # Dépendances Python
|
||||
├── README.md # Ce fichier
|
||||
└── TOOL-OPENWEBUI.md # Guide Tool OpenWebUI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Dépendances
|
||||
|
||||
- Python 3.11
|
||||
- FastAPI
|
||||
- Pillow (traitement d'images)
|
||||
- pytesseract (wrapper Tesseract)
|
||||
- Tesseract OCR 5.x
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Cas d'usage
|
||||
|
||||
- **Numérisation de livres** : Extraire le texte de photos de pages
|
||||
- **Factures** : Récupérer les informations de factures scannées
|
||||
- **Documents** : OCR sur PDF et images de documents
|
||||
- **Notes manuscrites** : Reconnaissance de texte manuscrit (limitée)
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Sécurité
|
||||
|
||||
- Le service écoute uniquement sur localhost (127.0.0.1:8300)
|
||||
- Aucune donnée n'est stockée persistante
|
||||
- Les images sont traitées en mémoire et supprimées après
|
||||
|
||||
---
|
||||
|
||||
Créé le 6 Avril 2026
|
||||
@@ -1,181 +0,0 @@
|
||||
# Tool OCR pour OpenWebUI
|
||||
|
||||
## Configuration
|
||||
|
||||
Dans OpenWebUI (http://192.168.1.27:3000) :
|
||||
|
||||
1. **Aller dans** : Admin → Tools → Create Tool
|
||||
2. **Nom** : OCR Extracteur de Texte
|
||||
3. **ID** : ocr_extractor
|
||||
4. **Description** : Extrait le texte des images pour les livres et documents
|
||||
|
||||
## Code du Tool
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
import requests
|
||||
import base64
|
||||
import os
|
||||
|
||||
class Tools:
|
||||
def __init__(self):
|
||||
"""Initialize OCR Tool"""
|
||||
self.ocr_url = os.getenv("OCR_URL", "http://192.168.1.11:8300")
|
||||
|
||||
def extract_text_from_image(self, image_path: str, language: str = "fra") -> str:
|
||||
"""
|
||||
Extract text from an image file using OCR
|
||||
|
||||
Args:
|
||||
image_path: Path to the image file (jpg, png, etc.)
|
||||
language: Language code (fra, eng, fra+eng, etc.)
|
||||
|
||||
Returns:
|
||||
Extracted text from the image
|
||||
"""
|
||||
try:
|
||||
# Read image file
|
||||
with open(image_path, 'rb') as f:
|
||||
files = {'file': f}
|
||||
data = {'lang': language}
|
||||
|
||||
response = requests.post(
|
||||
f"{self.ocr_url}/ocr",
|
||||
files=files,
|
||||
data=data,
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
if result.get('success'):
|
||||
text = result.get('text', '')
|
||||
char_count = result.get('characters_count', 0)
|
||||
word_count = result.get('words_count', 0)
|
||||
return f"Texte extrait ({char_count} caractères, {word_count} mots):\n\n{text}"
|
||||
else:
|
||||
return f"Erreur OCR: {result.get('error', 'Unknown error')}"
|
||||
else:
|
||||
return f"Erreur HTTP {response.status_code}: {response.text}"
|
||||
|
||||
except FileNotFoundError:
|
||||
return f"Erreur: Fichier non trouvé: {image_path}"
|
||||
except Exception as e:
|
||||
return f"Erreur lors de l'OCR: {str(e)}"
|
||||
|
||||
def extract_text_from_base64(self, image_base64: str, language: str = "fra") -> str:
|
||||
"""
|
||||
Extract text from a base64 encoded image
|
||||
|
||||
Args:
|
||||
image_base64: Base64 encoded image string
|
||||
language: Language code (fra, eng, fra+eng, etc.)
|
||||
|
||||
Returns:
|
||||
Extracted text from the image
|
||||
"""
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{self.ocr_url}/ocr/base64",
|
||||
json={
|
||||
'image_base64': image_base64,
|
||||
'lang': language,
|
||||
'preprocess': True
|
||||
},
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
if result.get('success'):
|
||||
text = result.get('text', '')
|
||||
char_count = result.get('characters_count', 0)
|
||||
word_count = result.get('words_count', 0)
|
||||
return f"Texte extrait ({char_count} caractères, {word_count} mots):\n\n{text}"
|
||||
else:
|
||||
return f"Erreur OCR: extraction échouée"
|
||||
else:
|
||||
return f"Erreur HTTP {response.status_code}: {response.text}"
|
||||
|
||||
except Exception as e:
|
||||
return f"Erreur lors de l'OCR: {str(e)}"
|
||||
|
||||
def get_available_languages(self) -> str:
|
||||
"""
|
||||
Get list of available OCR languages
|
||||
|
||||
Returns:
|
||||
List of available language codes
|
||||
"""
|
||||
try:
|
||||
response = requests.get(f"{self.ocr_url}/languages", timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
languages = result.get('available_languages', [])
|
||||
return f"Langues disponibles: {', '.join(languages)}"
|
||||
else:
|
||||
return f"Erreur: {response.status_code}"
|
||||
|
||||
except Exception as e:
|
||||
return f"Erreur: {str(e)}"
|
||||
```
|
||||
|
||||
## Variables d'environnement
|
||||
|
||||
Dans les Settings d'OpenWebUI (Admin → Settings → Environment Variables) :
|
||||
|
||||
**Si effi-ocr est sur le MEME serveur (recommandé):**
|
||||
```
|
||||
OCR_URL=http://host.docker.internal:8300
|
||||
```
|
||||
|
||||
**Si effi-ocr est sur un autre serveur (Fedora 192.168.1.11):**
|
||||
```
|
||||
OCR_URL=http://192.168.1.11:8300
|
||||
```
|
||||
|
||||
## Utilisation
|
||||
|
||||
Une fois le Tool créé, les agents pourront l'utiliser avec ces fonctions :
|
||||
|
||||
- `extract_text_from_image("/chemin/vers/image.jpg", "fra")` - Extraire le texte d'un fichier image
|
||||
- `extract_text_from_base64("base64encoded...", "fra")` - Extraire d'une image encodée en base64
|
||||
- `get_available_languages()` - Lister les langues disponibles
|
||||
|
||||
## Exemple de prompt
|
||||
|
||||
```
|
||||
"Effi, lis-moi ce texte" [upload d'image]
|
||||
→ L'agent utilise automatiquement le Tool OCR
|
||||
```
|
||||
|
||||
## Langues disponibles
|
||||
|
||||
- `fra` - Français
|
||||
- `eng` - Anglais
|
||||
- `fra+eng` - Français + Anglais (bilingue)
|
||||
- `deu` - Allemand
|
||||
- `spa` - Espagnol
|
||||
- `ita` - Italien
|
||||
|
||||
## Dépannage
|
||||
|
||||
**Erreur de connexion** :
|
||||
```bash
|
||||
# Vérifier que le service OCR tourne
|
||||
curl http://192.168.1.11:8300/health
|
||||
|
||||
# Redémarrer si nécessaire
|
||||
cd ~/Documents/OpenCode/Projets/Effi/effi-ocr
|
||||
sudo docker compose restart
|
||||
```
|
||||
|
||||
**Texte mal extrait** :
|
||||
- Essayer `fra+eng` pour les documents bilingues
|
||||
- Vérifier la qualité de l'image (résolution, contraste)
|
||||
- L'OCR fonctionne mieux avec des images bien éclairées
|
||||
|
||||
---
|
||||
|
||||
*Tool créé le 6 Avril 2026*
|
||||
@@ -1,80 +0,0 @@
|
||||
# Dépannage effi-OCR
|
||||
|
||||
## Problèmes Connus
|
||||
|
||||
### 1. "Fichier non trouvé" - Erreur Common
|
||||
|
||||
**Symptôme :**
|
||||
```
|
||||
Erreur: Fichier non trouvé pour l'ID: page_image.jpg (cherché dans /app/backend/data/uploads/)
|
||||
```
|
||||
|
||||
**Cause :**
|
||||
effi-ocr est sur une autre machine que OpenWebUI. Les chemins de fichiers ne sont pas partagés.
|
||||
|
||||
**Solution :**
|
||||
Installer effi-ocr sur le **MÊME serveur** qu'OpenWebUI (effi-server 192.168.1.27)
|
||||
|
||||
---
|
||||
|
||||
### 2. effi-ocr loop / se bloque
|
||||
|
||||
**Symptôme :**
|
||||
Le modèle répète "call the tool call the tool..." en boucle.
|
||||
|
||||
**Causes possibles :**
|
||||
- Tool mal configuré dans OpenWebUI
|
||||
- URL OCR_URL incorrecte
|
||||
- Le modèle a un problème avec le tool calling
|
||||
|
||||
**Solutions :**
|
||||
1. Vérifier que `OCR_URL` pointe vers le bon serveur
|
||||
2. Recréer le tool OCR dans OpenWebUI
|
||||
3. Désactiver Sub Agent/Planner Agent temporairement
|
||||
|
||||
---
|
||||
|
||||
### 3. OCR retourne du texte vide
|
||||
|
||||
**Causes possibles :**
|
||||
- Image de mauvaise qualité
|
||||
- Langue incorrecte (utiliser `fra+eng`)
|
||||
- Prétraitement désactivé
|
||||
|
||||
**Solutions :**
|
||||
1. Tester avec une image plus claire
|
||||
2. Utiliser `lang=fra+eng` pour documents mixtes
|
||||
3. Activer le prétraitement
|
||||
|
||||
---
|
||||
|
||||
## Checklist Diagnostic
|
||||
|
||||
- [ ] effi-ocr tourne sur le port 8300
|
||||
- [ ] OCR_URL est correct dans OpenWebUI
|
||||
- [ ] effi-ocr est sur le MÊME serveur qu'OpenWebUI
|
||||
- [ ] Le tool OCR est correctement créé dans Admin → Tools
|
||||
- [ ] Le fichier uploadé existe dans /app/backend/data/uploads/
|
||||
|
||||
---
|
||||
|
||||
## Commandes de Test
|
||||
|
||||
### Vérifier effi-ocr (sur le serveur où il tourne)
|
||||
```bash
|
||||
curl http://localhost:8300/health
|
||||
```
|
||||
|
||||
### Tester OCR avec une image
|
||||
```bash
|
||||
curl -X POST -F "file=@test.jpg" -F "lang=fra" http://localhost:8300/ocr
|
||||
```
|
||||
|
||||
### Vérifier les fichiers uploadés (OpenWebUI)
|
||||
```bash
|
||||
ls -la /app/backend/data/uploads/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Dernière mise à jour: Avril 2026*
|
||||
@@ -1,22 +0,0 @@
|
||||
services:
|
||||
effi-ocr:
|
||||
build: .
|
||||
container_name: effi-ocr
|
||||
ports:
|
||||
- "8300:8300"
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PYTHONUNBUFFERED=1
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8300/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
networks:
|
||||
- effi-network
|
||||
|
||||
networks:
|
||||
effi-network:
|
||||
external: true
|
||||
name: effi-network
|
||||
@@ -1,208 +0,0 @@
|
||||
"""
|
||||
Effi-OCR : Service OCR pour Effi
|
||||
API FastAPI qui expose Tesseract via une interface REST
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI, File, UploadFile, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from PIL import Image
|
||||
import pytesseract
|
||||
import io
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
# Configuration logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
app = FastAPI(
|
||||
title="Effi-OCR",
|
||||
description="Service OCR pour extraction de texte d'images",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
"""Endpoint de santé pour monitoring"""
|
||||
try:
|
||||
# Vérifier que Tesseract est accessible
|
||||
import subprocess
|
||||
result = subprocess.run(['tesseract', '--version'], capture_output=True, text=True)
|
||||
version_line = result.stdout.split('\n')[0] if result.stdout else "unknown"
|
||||
tesseract_version = str(version_line) # Forcer en string
|
||||
except Exception as e:
|
||||
tesseract_version = f"error: {str(e)}"
|
||||
|
||||
return {
|
||||
"status": "healthy",
|
||||
"service": "effi-ocr",
|
||||
"version": "1.0.0",
|
||||
"tesseract_version": tesseract_version
|
||||
}
|
||||
|
||||
|
||||
@app.post("/ocr")
|
||||
async def ocr_image(
|
||||
file: UploadFile = File(...),
|
||||
lang: str = "fra",
|
||||
preprocess: bool = True
|
||||
):
|
||||
"""
|
||||
Extraire le texte d'une image
|
||||
|
||||
Args:
|
||||
file: Image à analyser (jpg, png, etc.)
|
||||
lang: Code langue (fra, eng, fra+eng, etc.)
|
||||
preprocess: Appliquer un prétraitement pour améliorer la qualité
|
||||
|
||||
Returns:
|
||||
JSON avec le texte extrait et les métadonnées
|
||||
"""
|
||||
logger.info(f"OCR demandé - lang: {lang}, fichier: {file.filename}")
|
||||
|
||||
# Vérifier le type de fichier
|
||||
allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/tiff', 'image/webp']
|
||||
if file.content_type not in allowed_types:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Type de fichier non supporté: {file.content_type}. Types acceptés: {', '.join(allowed_types)}"
|
||||
)
|
||||
|
||||
try:
|
||||
# Lire l'image
|
||||
contents = await file.read()
|
||||
image = Image.open(io.BytesIO(contents))
|
||||
|
||||
# Convertir en RGB si nécessaire (pour les images avec transparence)
|
||||
if image.mode in ('RGBA', 'LA', 'P'):
|
||||
image = image.convert('RGB')
|
||||
|
||||
# Prétraitement optionnel pour améliorer la qualité OCR
|
||||
if preprocess:
|
||||
# Convertir en niveaux de gris pour meilleure détection texte
|
||||
image = image.convert('L')
|
||||
# Augmenter le contraste
|
||||
from PIL import ImageEnhance
|
||||
enhancer = ImageEnhance.Contrast(image)
|
||||
image = enhancer.enhance(2.0)
|
||||
|
||||
# OCR avec Tesseract
|
||||
text = pytesseract.image_to_string(image, lang=lang)
|
||||
|
||||
# Nettoyer le texte
|
||||
text = text.strip()
|
||||
|
||||
# Informations sur l'image
|
||||
width, height = image.size
|
||||
|
||||
logger.info(f"OCR terminé - {len(text)} caractères extraits")
|
||||
|
||||
return JSONResponse(content={
|
||||
"success": True,
|
||||
"text": text,
|
||||
"language": lang,
|
||||
"filename": file.filename,
|
||||
"image_size": {"width": width, "height": height},
|
||||
"characters_count": len(text),
|
||||
"words_count": len(text.split()) if text else 0
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur OCR: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail=f"Erreur lors de l'OCR: {str(e)}")
|
||||
|
||||
|
||||
@app.post("/ocr/base64")
|
||||
async def ocr_base64(
|
||||
image_base64: str,
|
||||
lang: str = "fra",
|
||||
preprocess: bool = True
|
||||
):
|
||||
"""
|
||||
Extraire le texte d'une image en base64
|
||||
|
||||
Args:
|
||||
image_base64: Image encodée en base64
|
||||
lang: Code langue (fra, eng, fra+eng, etc.)
|
||||
preprocess: Appliquer un prétraitement
|
||||
|
||||
Returns:
|
||||
JSON avec le texte extrait
|
||||
"""
|
||||
import base64
|
||||
|
||||
logger.info(f"OCR base64 demandé - lang: {lang}")
|
||||
|
||||
try:
|
||||
# Décoder le base64
|
||||
image_data = base64.b64decode(image_base64)
|
||||
image = Image.open(io.BytesIO(image_data))
|
||||
|
||||
# Convertir en RGB si nécessaire
|
||||
if image.mode in ('RGBA', 'LA', 'P'):
|
||||
image = image.convert('RGB')
|
||||
|
||||
# Prétraitement
|
||||
if preprocess:
|
||||
image = image.convert('L')
|
||||
from PIL import ImageEnhance
|
||||
enhancer = ImageEnhance.Contrast(image)
|
||||
image = enhancer.enhance(2.0)
|
||||
|
||||
# OCR
|
||||
text = pytesseract.image_to_string(image, lang=lang)
|
||||
text = text.strip()
|
||||
|
||||
width, height = image.size
|
||||
|
||||
logger.info(f"OCR base64 terminé - {len(text)} caractères")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"text": text,
|
||||
"language": lang,
|
||||
"image_size": {"width": width, "height": height},
|
||||
"characters_count": len(text),
|
||||
"words_count": len(text.split()) if text else 0
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur OCR base64: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail=f"Erreur lors de l'OCR: {str(e)}")
|
||||
|
||||
|
||||
@app.get("/languages")
|
||||
async def list_languages():
|
||||
"""Lister les langues disponibles pour l'OCR"""
|
||||
try:
|
||||
# Commande tesseract pour lister les langues
|
||||
import subprocess
|
||||
result = subprocess.run(
|
||||
['tesseract', '--list-langs'],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
|
||||
# Parser la sortie
|
||||
lines = result.stdout.strip().split('\n')
|
||||
# La première ligne est "List of available languages (xxx):"
|
||||
languages = lines[1:] if len(lines) > 1 else []
|
||||
|
||||
return {
|
||||
"available_languages": languages,
|
||||
"count": len(languages)
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur listage langues: {str(e)}")
|
||||
# Fallback avec les langues communes
|
||||
return {
|
||||
"available_languages": ["fra", "eng", "fra+eng", "deu", "spa", "ita"],
|
||||
"count": 6,
|
||||
"note": "Liste par défaut, erreur lors de la récupération"
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8300)
|
||||
@@ -1,5 +0,0 @@
|
||||
fastapi==0.109.0
|
||||
uvicorn[standard]==0.27.0
|
||||
python-multipart==0.0.6
|
||||
pillow==10.2.0
|
||||
pytesseract==0.3.10
|
||||
Reference in New Issue
Block a user