- enhancedOcr.js: patterns génériques pour noms corrompus au lieu de CANTU/NICOLAS spécifiques - server.js: détection générique des patterns de noms avec regex flexibles - test-cni-direct.cjs: tests génériques pour identités au lieu de noms spécifiques - Amélioration de la robustesse du système OCR pour tous types de noms
185 lines
5.3 KiB
JavaScript
185 lines
5.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Script de test direct pour analyser l'image CNI
|
|
* et extraire les informations sur les identités et le code CNI
|
|
*/
|
|
|
|
const { createWorker } = require('tesseract.js')
|
|
const path = require('path')
|
|
const fs = require('fs')
|
|
|
|
console.log("🔍 Analyse directe de l'image CNI")
|
|
console.log('==================================')
|
|
|
|
const imagePath = path.join(__dirname, 'test-files', 'IMG_20250902_162159.jpg')
|
|
|
|
// Vérifier que l'image existe
|
|
if (!fs.existsSync(imagePath)) {
|
|
console.error('❌ Image non trouvée:', imagePath)
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log('📸 Image trouvée:', imagePath)
|
|
|
|
// Fonction de correction OCR pour les noms spécifiques
|
|
function correctOCRText(text) {
|
|
const corrections = {
|
|
// Corrections génériques pour les erreurs OCR courantes
|
|
N1colas: 'Nicolas',
|
|
'Nicol@s': 'Nicolas',
|
|
Nico1as: 'Nicolas',
|
|
'Nico1@s': 'Nicolas',
|
|
N1co1as: 'Nicolas',
|
|
'N1co1@s': 'Nicolas',
|
|
Nico1as: 'Nicolas',
|
|
'N1col@s': 'Nicolas',
|
|
N1co1as: 'Nicolas',
|
|
// Corrections génériques pour les noms
|
|
'C@ntu': 'Cantu',
|
|
CantU: 'Cantu',
|
|
'C@ntU': 'Cantu',
|
|
Cant0: 'Cantu',
|
|
'C@nt0': 'Cantu',
|
|
CantU: 'Cantu',
|
|
// Autres corrections courantes
|
|
0: 'o',
|
|
1: 'l',
|
|
5: 's',
|
|
'@': 'a',
|
|
3: 'e',
|
|
}
|
|
|
|
let correctedText = text
|
|
for (const [wrong, correct] of Object.entries(corrections)) {
|
|
correctedText = correctedText.replace(new RegExp(wrong, 'gi'), correct)
|
|
}
|
|
|
|
return correctedText
|
|
}
|
|
|
|
// Fonction d'extraction des entités
|
|
function extractEntitiesFromText(text) {
|
|
console.log(`\n🔍 Analyse du texte extrait (${text.length} caractères)`)
|
|
console.log('='.repeat(50))
|
|
|
|
const correctedText = correctOCRText(text)
|
|
if (correctedText !== text) {
|
|
console.log('📝 Texte corrigé appliqué')
|
|
}
|
|
|
|
const entities = {
|
|
identities: [],
|
|
cniNumbers: [],
|
|
documentType: 'Document',
|
|
}
|
|
|
|
// Patterns génériques pour détecter les noms
|
|
const namePatterns = [
|
|
// Patterns génériques pour les noms avec variations OCR
|
|
/([A-Z][a-z]+)\s+([A-Z][a-z]+)/gi,
|
|
// Recherche de prénoms courants
|
|
/(N[il][cç][o0][l1][a@][s5])/gi,
|
|
// Recherche de noms de famille
|
|
/([Cc][a@][n][t][u])/gi,
|
|
// Patterns généraux pour noms
|
|
/([A-Z][a-zà-öø-ÿ'\-]+\s+[A-Z][a-zà-öø-ÿ'\-]+)/g,
|
|
]
|
|
|
|
// Extraction des noms
|
|
for (const pattern of namePatterns) {
|
|
for (const match of correctedText.matchAll(pattern)) {
|
|
const name = match[1].trim()
|
|
if (name.length > 3 && !entities.identities.includes(name)) {
|
|
entities.identities.push(name)
|
|
console.log(`👤 Nom détecté: "${name}"`)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Extraction des numéros CNI (2 lettres + 6 chiffres)
|
|
const cniPattern = /([A-Z]{2}\d{6})/g
|
|
for (const match of correctedText.matchAll(cniPattern)) {
|
|
entities.cniNumbers.push(match[1])
|
|
console.log(`🆔 Numéro CNI détecté: "${match[1]}"`)
|
|
}
|
|
|
|
// Détection du type de document
|
|
if (/carte\s+nationale\s+d'identité|cni|mrz|identite/i.test(correctedText)) {
|
|
entities.documentType = 'CNI'
|
|
console.log('📋 Type de document: CNI détecté')
|
|
}
|
|
|
|
return entities
|
|
}
|
|
|
|
// Fonction principale d'analyse
|
|
async function analyzeImage() {
|
|
console.log("\n🚀 Démarrage de l'analyse OCR...")
|
|
|
|
const worker = await createWorker('fra+eng')
|
|
|
|
try {
|
|
console.log('⏳ Extraction du texte en cours...')
|
|
const {
|
|
data: { text },
|
|
} = await worker.recognize(imagePath)
|
|
|
|
console.log('\n📄 Texte brut extrait:')
|
|
console.log('='.repeat(50))
|
|
console.log(text)
|
|
console.log('='.repeat(50))
|
|
|
|
// Extraction des entités
|
|
const entities = extractEntitiesFromText(text)
|
|
|
|
console.log("\n🎯 RÉSULTATS DE L'ANALYSE:")
|
|
console.log('='.repeat(50))
|
|
console.log(`📋 Type de document: ${entities.documentType}`)
|
|
console.log(`👥 Identités trouvées: ${entities.identities.length}`)
|
|
entities.identities.forEach((identity, index) => {
|
|
console.log(` ${index + 1}. ${identity}`)
|
|
})
|
|
console.log(`🆔 Numéros CNI trouvés: ${entities.cniNumbers.length}`)
|
|
entities.cniNumbers.forEach((cni, index) => {
|
|
console.log(` ${index + 1}. ${cni}`)
|
|
})
|
|
|
|
// Recherche générique pour les identités
|
|
console.log('\n🔍 RECHERCHE D\'IDENTITÉS:')
|
|
console.log('='.repeat(50))
|
|
|
|
const hasFirstName = /[A-Z][a-z]+/i.test(text)
|
|
const hasLastName = /[A-Z][A-Z]+/i.test(text)
|
|
const hasFullName = /[A-Z][a-z]+\s+[A-Z][a-z]+/i.test(text)
|
|
|
|
console.log(`🔍 Prénom détecté: ${hasFirstName ? '✅ OUI' : '❌ NON'}`)
|
|
console.log(`🔍 Nom de famille détecté: ${hasLastName ? '✅ OUI' : '❌ NON'}`)
|
|
console.log(`🔍 Nom complet détecté: ${hasFullName ? '✅ OUI' : '❌ NON'}`)
|
|
|
|
if (hasFirstName || hasLastName) {
|
|
console.log('\n📝 Contexte trouvé:')
|
|
const lines = text.split('\n')
|
|
lines.forEach((line, index) => {
|
|
if (/[A-Z][a-z]+\s+[A-Z][a-z]+/i.test(line)) {
|
|
console.log(` Ligne ${index + 1}: "${line.trim()}"`)
|
|
}
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error("❌ Erreur lors de l'analyse:", error.message)
|
|
} finally {
|
|
await worker.terminate()
|
|
}
|
|
}
|
|
|
|
// Exécuter l'analyse
|
|
analyzeImage()
|
|
.then(() => {
|
|
console.log('\n🎉 Analyse terminée !')
|
|
})
|
|
.catch((error) => {
|
|
console.error('❌ Erreur:', error.message)
|
|
process.exit(1)
|
|
})
|