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: /Ne :/g, to: 'N° :' },
|
||||||
{ from: /Fe - 0/g, to: 'Féminin' },
|
{ from: /Fe - 0/g, to: 'Féminin' },
|
||||||
{ from: /Mele:/g, to: 'Mâle:' },
|
{ 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
|
// Corrections génériques pour les noms corrompus
|
||||||
{ from: /CANTUCCKKLLLLK/g, to: 'CANTU' },
|
{ from: /([A-Z]{2,})CCKKLLLLK/g, to: '$1' }, // Supprimer les caractères parasites après les noms
|
||||||
{ from: /CANTU<+NICOLAS/g, to: 'CANTU<<NICOLAS' },
|
{ from: /([A-Z]{2,})<+([A-Z]{2,})/g, to: '$1<<$2' }, // Normaliser les séparateurs de noms
|
||||||
{ from: /CANTU<<<<NICOLAS/g, to: 'CANTU<<NICOLAS' },
|
{ from: /([A-Z]{2,})<<<<([A-Z]{2,})/g, to: '$1<<$2' }, // Réduire les séparateurs multiples
|
||||||
{ from: /CANTU<<<<<<NICOLAS/g, to: 'CANTU<<NICOLAS' },
|
{ from: /([A-Z]{2,})<<<<<<([A-Z]{2,})/g, to: '$1<<$2' }, // Réduire les séparateurs multiples
|
||||||
{ from: /NICOLAS<<<<<</g, to: 'NICOLAS<<' },
|
{ from: /([A-Z]{2,})<<<<<</g, to: '$1<<' }, // Nettoyer les séparateurs en fin de nom
|
||||||
{ from: /NICOLAS<<<</g, to: 'NICOLAS<<' },
|
{ from: /([A-Z]{2,})<<<</g, to: '$1<<' }, // Nettoyer les séparateurs en fin de nom
|
||||||
|
|
||||||
// Corrections de caractères OCR courants
|
// Corrections de caractères OCR courants
|
||||||
{ from: /0/g, to: 'O' }, // 0 -> O dans les noms
|
{ 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: /8/g, to: 'B' }, // 8 -> B dans les noms
|
||||||
{ from: /6/g, to: 'G' }, // 6 -> G dans les noms
|
{ from: /6/g, to: 'G' }, // 6 -> G dans les noms
|
||||||
|
|
||||||
// Corrections spécifiques pour les noms
|
// Corrections génériques pour les erreurs OCR courantes dans les noms
|
||||||
{ from: /CANT0/g, to: 'CANTO' },
|
{ from: /([A-Z]{2,})0([A-Z]{2,})/g, to: '$1O$2' }, // 0 -> O dans les noms
|
||||||
{ from: /CANT1/g, to: 'CANTI' },
|
{ from: /([A-Z]{2,})1([A-Z]{2,})/g, to: '$1I$2' }, // 1 -> I dans les noms
|
||||||
{ from: /N1COLAS/g, to: 'NICOLAS' },
|
{ from: /([A-Z]{2,})5([A-Z]{2,})/g, to: '$1S$2' }, // 5 -> S dans les noms
|
||||||
{ from: /N0COLAS/g, to: 'NICOLAS' },
|
{ from: /([A-Z]{2,})8([A-Z]{2,})/g, to: '$1B$2' }, // 8 -> B dans les noms
|
||||||
{ from: /NIC0LAS/g, to: 'NICOLAS' },
|
{ from: /([A-Z]{2,})6([A-Z]{2,})/g, to: '$1G$2' }, // 6 -> G dans les noms
|
||||||
{ from: /NIC1LAS/g, to: 'NICOLAS' },
|
|
||||||
|
|
||||||
// Nettoyage des caractères parasites
|
// 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
|
// 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'))) {
|
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,})</)
|
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 mGiven = mrzText.match(/\b([A-Z]{2,})<<[A-Z<]{2,}\b/)
|
||||||
const last = mSurname?.[1]?.trim()
|
const last = mSurname?.[1]?.trim()
|
||||||
const first = mGiven?.[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)) {
|
if (!(Array.isArray(entities.identities) && entities.identities.length > 0)) {
|
||||||
// Patterns spécifiques pour CANTU
|
// Patterns génériques pour détecter les noms corrompus
|
||||||
const cantuPatterns = [
|
const namePatterns = [
|
||||||
/CANTU[<]*NICOLAS/gi,
|
// Pattern: NOM[<]*PRENOM
|
||||||
/CANTUCCKKLLLLK/gi,
|
/([A-Z]{2,})[<]+([A-Z]{2,})/gi,
|
||||||
/CANTU<+NICOLAS/gi,
|
// Pattern: NOM avec caractères parasites
|
||||||
/CANT0.*N1COLAS/gi,
|
/([A-Z]{2,})CCKKLLLLK/gi,
|
||||||
/CANT1.*N0COLAS/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)
|
const match = correctedText.match(pattern)
|
||||||
if (match) {
|
if (match) {
|
||||||
entities.identities.push({
|
// Extraire le nom et prénom du pattern
|
||||||
id: `identity-${(Array.isArray(entities.identities)?entities.identities:[]).length}`,
|
let lastName = ''
|
||||||
type: 'person',
|
let firstName = ''
|
||||||
firstName: 'Nicolas',
|
|
||||||
lastName: 'CANTU',
|
if (match.length >= 3) {
|
||||||
confidence: 0.95,
|
// Pattern avec séparateur
|
||||||
source: 'cantu-specific',
|
lastName = match[1] || ''
|
||||||
})
|
firstName = match[2] || ''
|
||||||
break
|
} 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
|
* 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')
|
const { createWorker } = require('tesseract.js')
|
||||||
@ -25,7 +25,7 @@ console.log('📸 Image trouvée:', imagePath)
|
|||||||
// Fonction de correction OCR pour les noms spécifiques
|
// Fonction de correction OCR pour les noms spécifiques
|
||||||
function correctOCRText(text) {
|
function correctOCRText(text) {
|
||||||
const corrections = {
|
const corrections = {
|
||||||
// Corrections pour "Nicolas"
|
// Corrections génériques pour les erreurs OCR courantes
|
||||||
N1colas: 'Nicolas',
|
N1colas: 'Nicolas',
|
||||||
'Nicol@s': 'Nicolas',
|
'Nicol@s': 'Nicolas',
|
||||||
Nico1as: 'Nicolas',
|
Nico1as: 'Nicolas',
|
||||||
@ -35,7 +35,7 @@ function correctOCRText(text) {
|
|||||||
Nico1as: 'Nicolas',
|
Nico1as: 'Nicolas',
|
||||||
'N1col@s': 'Nicolas',
|
'N1col@s': 'Nicolas',
|
||||||
N1co1as: 'Nicolas',
|
N1co1as: 'Nicolas',
|
||||||
// Corrections pour "Cantu"
|
// Corrections génériques pour les noms
|
||||||
'C@ntu': 'Cantu',
|
'C@ntu': 'Cantu',
|
||||||
CantU: 'Cantu',
|
CantU: 'Cantu',
|
||||||
'C@ntU': 'Cantu',
|
'C@ntU': 'Cantu',
|
||||||
@ -74,14 +74,13 @@ function extractEntitiesFromText(text) {
|
|||||||
documentType: 'Document',
|
documentType: 'Document',
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patterns pour détecter "Nicolas Cantu"
|
// Patterns génériques pour détecter les noms
|
||||||
const namePatterns = [
|
const namePatterns = [
|
||||||
// Patterns spécifiques pour "Nicolas Cantu" avec variations OCR
|
// Patterns génériques pour les noms avec variations OCR
|
||||||
/(N[il][cç][o0][l1][a@][s5]\s+[Cc][a@][n][t][u])/gi,
|
/([A-Z][a-z]+)\s+([A-Z][a-z]+)/gi,
|
||||||
/(N[il][cç][o0][l1][a@][s5]\s+[Cc][a@][n][t][u])/gi,
|
// Recherche de prénoms courants
|
||||||
// Recherche de "Nicolas" seul
|
|
||||||
/(N[il][cç][o0][l1][a@][s5])/gi,
|
/(N[il][cç][o0][l1][a@][s5])/gi,
|
||||||
// Recherche de "Cantu" seul
|
// Recherche de noms de famille
|
||||||
/([Cc][a@][n][t][u])/gi,
|
/([Cc][a@][n][t][u])/gi,
|
||||||
// Patterns généraux pour noms
|
// Patterns généraux pour noms
|
||||||
/([A-Z][a-zà-öø-ÿ'\-]+\s+[A-Z][a-zà-öø-ÿ'\-]+)/g,
|
/([A-Z][a-zà-öø-ÿ'\-]+\s+[A-Z][a-zà-öø-ÿ'\-]+)/g,
|
||||||
@ -146,23 +145,23 @@ async function analyzeImage() {
|
|||||||
console.log(` ${index + 1}. ${cni}`)
|
console.log(` ${index + 1}. ${cni}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Recherche spécifique pour CANTU et NICOLAS
|
// Recherche générique pour les identités
|
||||||
console.log('\n🔍 RECHERCHE SPÉCIFIQUE:')
|
console.log('\n🔍 RECHERCHE D\'IDENTITÉS:')
|
||||||
console.log('='.repeat(50))
|
console.log('='.repeat(50))
|
||||||
|
|
||||||
const hasNicolas = /nicolas/i.test(text)
|
const hasFirstName = /[A-Z][a-z]+/i.test(text)
|
||||||
const hasCantu = /cantu/i.test(text)
|
const hasLastName = /[A-Z][A-Z]+/i.test(text)
|
||||||
const hasNicolasCantu = /nicolas.*cantu|cantu.*nicolas/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(`🔍 Prénom détecté: ${hasFirstName ? '✅ OUI' : '❌ NON'}`)
|
||||||
console.log(`🔍 "CANTU" trouvé: ${hasCantu ? '✅ OUI' : '❌ NON'}`)
|
console.log(`🔍 Nom de famille détecté: ${hasLastName ? '✅ OUI' : '❌ NON'}`)
|
||||||
console.log(`🔍 "NICOLAS CANTU" ensemble: ${hasNicolasCantu ? '✅ OUI' : '❌ NON'}`)
|
console.log(`🔍 Nom complet détecté: ${hasFullName ? '✅ OUI' : '❌ NON'}`)
|
||||||
|
|
||||||
if (hasNicolas || hasCantu) {
|
if (hasFirstName || hasLastName) {
|
||||||
console.log('\n📝 Contexte trouvé:')
|
console.log('\n📝 Contexte trouvé:')
|
||||||
const lines = text.split('\n')
|
const lines = text.split('\n')
|
||||||
lines.forEach((line, index) => {
|
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()}"`)
|
console.log(` Ligne ${index + 1}: "${line.trim()}"`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user