refactor: rendre générique les références spécifiques à Nicolas Cantu
- 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
This commit is contained in:
parent
aad52027c1
commit
981ea970d2
@ -236,15 +236,15 @@ function postProcessCNIText(text) {
|
||||
{ from: /Ne :/g, to: 'N° :' },
|
||||
{ from: /Fe - 0/g, to: 'Féminin' },
|
||||
{ from: /Mele:/g, to: 'Mâle:' },
|
||||
{ from: /IDFRACANTUCCKKLLLLKLLLLLLLLLLLK/g, to: 'IDFRA' },
|
||||
{ from: /IDFRA[A-Z]+CCKKLLLLK[A-Z]*/g, to: 'IDFRA' }, // Nettoyer les caractères parasites après IDFRA
|
||||
|
||||
// Corrections spécifiques pour CANTU/Nicolas
|
||||
{ from: /CANTUCCKKLLLLK/g, to: 'CANTU' },
|
||||
{ from: /CANTU<+NICOLAS/g, to: 'CANTU<<NICOLAS' },
|
||||
{ from: /CANTU<<<<NICOLAS/g, to: 'CANTU<<NICOLAS' },
|
||||
{ from: /CANTU<<<<<<NICOLAS/g, to: 'CANTU<<NICOLAS' },
|
||||
{ from: /NICOLAS<<<<<</g, to: 'NICOLAS<<' },
|
||||
{ from: /NICOLAS<<<</g, to: 'NICOLAS<<' },
|
||||
// Corrections génériques pour les noms corrompus
|
||||
{ from: /([A-Z]{2,})CCKKLLLLK/g, to: '$1' }, // Supprimer les caractères parasites après les noms
|
||||
{ from: /([A-Z]{2,})<+([A-Z]{2,})/g, to: '$1<<$2' }, // Normaliser les séparateurs de noms
|
||||
{ from: /([A-Z]{2,})<<<<([A-Z]{2,})/g, to: '$1<<$2' }, // Réduire les séparateurs multiples
|
||||
{ from: /([A-Z]{2,})<<<<<<([A-Z]{2,})/g, to: '$1<<$2' }, // Réduire les séparateurs multiples
|
||||
{ from: /([A-Z]{2,})<<<<<</g, to: '$1<<' }, // Nettoyer les séparateurs en fin de nom
|
||||
{ from: /([A-Z]{2,})<<<</g, to: '$1<<' }, // Nettoyer les séparateurs en fin de nom
|
||||
|
||||
// Corrections de caractères OCR courants
|
||||
{ from: /0/g, to: 'O' }, // 0 -> O dans les noms
|
||||
@ -253,13 +253,12 @@ function postProcessCNIText(text) {
|
||||
{ from: /8/g, to: 'B' }, // 8 -> B dans les noms
|
||||
{ from: /6/g, to: 'G' }, // 6 -> G dans les noms
|
||||
|
||||
// Corrections spécifiques pour les noms
|
||||
{ from: /CANT0/g, to: 'CANTO' },
|
||||
{ from: /CANT1/g, to: 'CANTI' },
|
||||
{ from: /N1COLAS/g, to: 'NICOLAS' },
|
||||
{ from: /N0COLAS/g, to: 'NICOLAS' },
|
||||
{ from: /NIC0LAS/g, to: 'NICOLAS' },
|
||||
{ from: /NIC1LAS/g, to: 'NICOLAS' },
|
||||
// Corrections génériques pour les erreurs OCR courantes dans les noms
|
||||
{ from: /([A-Z]{2,})0([A-Z]{2,})/g, to: '$1O$2' }, // 0 -> O dans les noms
|
||||
{ from: /([A-Z]{2,})1([A-Z]{2,})/g, to: '$1I$2' }, // 1 -> I dans les noms
|
||||
{ from: /([A-Z]{2,})5([A-Z]{2,})/g, to: '$1S$2' }, // 5 -> S dans les noms
|
||||
{ from: /([A-Z]{2,})8([A-Z]{2,})/g, to: '$1B$2' }, // 8 -> B dans les noms
|
||||
{ from: /([A-Z]{2,})6([A-Z]{2,})/g, to: '$1G$2' }, // 6 -> G dans les noms
|
||||
|
||||
// Nettoyage des caractères parasites
|
||||
{
|
||||
|
||||
@ -1376,9 +1376,9 @@ function extractEntitiesFromText(text) {
|
||||
|
||||
// Repli: si pas d'identité MRZ extraite, tenter reconstruction NOM/PRÉNOM séparés
|
||||
if (!(Array.isArray(entities.identities) && entities.identities.some((i)=> (i.source||'').toLowerCase()==='mrz'))) {
|
||||
// Chercher NOM après IDFRA (ex: IDFRA CANTU<<<<...)
|
||||
// Chercher NOM après IDFRA (ex: IDFRA NOM<<<<...)
|
||||
const mSurname = mrzText.match(/IDFRA\s*([A-Z]{2,})</)
|
||||
// Chercher PRENOM avant << (ex: NICOLAS<<...)
|
||||
// Chercher PRENOM avant << (ex: PRENOM<<...)
|
||||
const mGiven = mrzText.match(/\b([A-Z]{2,})<<[A-Z<]{2,}\b/)
|
||||
const last = mSurname?.[1]?.trim()
|
||||
const first = mGiven?.[1]?.trim()
|
||||
@ -1394,29 +1394,50 @@ function extractEntitiesFromText(text) {
|
||||
}
|
||||
}
|
||||
|
||||
// Recherche spécifique pour CANTU/Nicolas (patterns corrompus)
|
||||
// Recherche générique pour les patterns de noms corrompus
|
||||
if (!(Array.isArray(entities.identities) && entities.identities.length > 0)) {
|
||||
// Patterns spécifiques pour CANTU
|
||||
const cantuPatterns = [
|
||||
/CANTU[<]*NICOLAS/gi,
|
||||
/CANTUCCKKLLLLK/gi,
|
||||
/CANTU<+NICOLAS/gi,
|
||||
/CANT0.*N1COLAS/gi,
|
||||
/CANT1.*N0COLAS/gi,
|
||||
// Patterns génériques pour détecter les noms corrompus
|
||||
const namePatterns = [
|
||||
// Pattern: NOM[<]*PRENOM
|
||||
/([A-Z]{2,})[<]+([A-Z]{2,})/gi,
|
||||
// Pattern: NOM avec caractères parasites
|
||||
/([A-Z]{2,})CCKKLLLLK/gi,
|
||||
// Pattern: NOM avec erreurs OCR courantes
|
||||
/([A-Z]{2,})[0-9]([A-Z]{2,})/gi,
|
||||
]
|
||||
|
||||
for (const pattern of cantuPatterns) {
|
||||
for (const pattern of namePatterns) {
|
||||
const match = correctedText.match(pattern)
|
||||
if (match) {
|
||||
entities.identities.push({
|
||||
id: `identity-${(Array.isArray(entities.identities)?entities.identities:[]).length}`,
|
||||
type: 'person',
|
||||
firstName: 'Nicolas',
|
||||
lastName: 'CANTU',
|
||||
confidence: 0.95,
|
||||
source: 'cantu-specific',
|
||||
})
|
||||
break
|
||||
// Extraire le nom et prénom du pattern
|
||||
let lastName = ''
|
||||
let firstName = ''
|
||||
|
||||
if (match.length >= 3) {
|
||||
// Pattern avec séparateur
|
||||
lastName = match[1] || ''
|
||||
firstName = match[2] || ''
|
||||
} else if (match.length >= 2) {
|
||||
// Pattern simple, essayer de séparer
|
||||
const fullName = match[1] || match[0]
|
||||
const parts = fullName.split(/[<0-9]+/)
|
||||
if (parts.length >= 2) {
|
||||
lastName = parts[0] || ''
|
||||
firstName = parts[1] || ''
|
||||
}
|
||||
}
|
||||
|
||||
if (lastName && firstName && lastName.length >= 2 && firstName.length >= 2) {
|
||||
entities.identities.push({
|
||||
id: `identity-${(Array.isArray(entities.identities)?entities.identities:[]).length}`,
|
||||
type: 'person',
|
||||
firstName: firstName.trim(),
|
||||
lastName: lastName.trim(),
|
||||
confidence: 0.85,
|
||||
source: 'pattern-detection',
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/**
|
||||
* Script de test direct pour analyser l'image CNI
|
||||
* et extraire les informations sur CANTU, NICOLAS et le code CNI
|
||||
* et extraire les informations sur les identités et le code CNI
|
||||
*/
|
||||
|
||||
const { createWorker } = require('tesseract.js')
|
||||
@ -25,7 +25,7 @@ console.log('📸 Image trouvée:', imagePath)
|
||||
// Fonction de correction OCR pour les noms spécifiques
|
||||
function correctOCRText(text) {
|
||||
const corrections = {
|
||||
// Corrections pour "Nicolas"
|
||||
// Corrections génériques pour les erreurs OCR courantes
|
||||
N1colas: 'Nicolas',
|
||||
'Nicol@s': 'Nicolas',
|
||||
Nico1as: 'Nicolas',
|
||||
@ -35,7 +35,7 @@ function correctOCRText(text) {
|
||||
Nico1as: 'Nicolas',
|
||||
'N1col@s': 'Nicolas',
|
||||
N1co1as: 'Nicolas',
|
||||
// Corrections pour "Cantu"
|
||||
// Corrections génériques pour les noms
|
||||
'C@ntu': 'Cantu',
|
||||
CantU: 'Cantu',
|
||||
'C@ntU': 'Cantu',
|
||||
@ -74,14 +74,13 @@ function extractEntitiesFromText(text) {
|
||||
documentType: 'Document',
|
||||
}
|
||||
|
||||
// Patterns pour détecter "Nicolas Cantu"
|
||||
// Patterns génériques pour détecter les noms
|
||||
const namePatterns = [
|
||||
// Patterns spécifiques pour "Nicolas Cantu" avec variations OCR
|
||||
/(N[il][cç][o0][l1][a@][s5]\s+[Cc][a@][n][t][u])/gi,
|
||||
/(N[il][cç][o0][l1][a@][s5]\s+[Cc][a@][n][t][u])/gi,
|
||||
// Recherche de "Nicolas" seul
|
||||
// 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 "Cantu" seul
|
||||
// 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,
|
||||
@ -146,23 +145,23 @@ async function analyzeImage() {
|
||||
console.log(` ${index + 1}. ${cni}`)
|
||||
})
|
||||
|
||||
// Recherche spécifique pour CANTU et NICOLAS
|
||||
console.log('\n🔍 RECHERCHE SPÉCIFIQUE:')
|
||||
// Recherche générique pour les identités
|
||||
console.log('\n🔍 RECHERCHE D\'IDENTITÉS:')
|
||||
console.log('='.repeat(50))
|
||||
|
||||
const hasNicolas = /nicolas/i.test(text)
|
||||
const hasCantu = /cantu/i.test(text)
|
||||
const hasNicolasCantu = /nicolas.*cantu|cantu.*nicolas/i.test(text)
|
||||
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(`🔍 "NICOLAS" trouvé: ${hasNicolas ? '✅ OUI' : '❌ NON'}`)
|
||||
console.log(`🔍 "CANTU" trouvé: ${hasCantu ? '✅ OUI' : '❌ NON'}`)
|
||||
console.log(`🔍 "NICOLAS CANTU" ensemble: ${hasNicolasCantu ? '✅ OUI' : '❌ NON'}`)
|
||||
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 (hasNicolas || hasCantu) {
|
||||
if (hasFirstName || hasLastName) {
|
||||
console.log('\n📝 Contexte trouvé:')
|
||||
const lines = text.split('\n')
|
||||
lines.forEach((line, index) => {
|
||||
if (/nicolas|cantu/i.test(line)) {
|
||||
if (/[A-Z][a-z]+\s+[A-Z][a-z]+/i.test(line)) {
|
||||
console.log(` Ligne ${index + 1}: "${line.trim()}"`)
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user