Merged in bugfix/handwritten-npi-list-updated (pull request #850)
fix ocr issue in list of NPIs * fix ocr issue in list od NPIs * pipeline error fixed Approved-by: Katon Minhas
This commit is contained in:
committed by
Katon Minhas
parent
afb6d5185d
commit
929ff4abf8
@@ -40,7 +40,7 @@ NPI_PATTERN = r"\b(?:\d\s*){10}\b"
|
||||
TIN_OCR_PATTERN = r"\b[O0lI1S5G6B8gbo\d]{9}\b|\b[O0lI1S5G6B8gbo\d]{2}[-.][O0lI1S5G6B8gbo\d]{7}\b|\b[O0lI1S5G6B8gbo\d]{3}[-.][O0lI1S5G6B8gbo\d]{2}[-.][O0lI1S5G6B8gbo\d]{4}\b"
|
||||
|
||||
# OCR-Correctable NPI Pattern
|
||||
# Strategy: Match 10-character sequences containing digits and OCR-prone letters,
|
||||
# Strategy: Match 10-character sequences containing digits and OCR-prone letters; also Matches "chained" NPIs separated by '1', 'l', or 'I'.
|
||||
# then apply corrections post-match to validate it becomes a proper 10-digit NPI.
|
||||
#
|
||||
# Examples that WILL be captured and corrected:
|
||||
@@ -48,6 +48,7 @@ TIN_OCR_PATTERN = r"\b[O0lI1S5G6B8gbo\d]{9}\b|\b[O0lI1S5G6B8gbo\d]{2}[-.][O0lI1S
|
||||
# - "l234567890" → "1234567890" (l at start)
|
||||
# - "12345O7890" → "1234507890" (O in middle)
|
||||
# - "123456789l" → "1234567891" (l at end)
|
||||
# - "123456789011234567890" (seen as NPI + "1" + NPI)
|
||||
#
|
||||
# Examples that will NOT match:
|
||||
# - "123456789" (only 9 characters)
|
||||
@@ -57,7 +58,7 @@ TIN_OCR_PATTERN = r"\b[O0lI1S5G6B8gbo\d]{9}\b|\b[O0lI1S5G6B8gbo\d]{2}[-.][O0lI1S
|
||||
# Note: NPIs are always unformatted 10-digit numbers, so no hyphen/dot variations.
|
||||
# Validation happens post-match by applying OCR_SUBSTITUTIONS and checking
|
||||
# that result is exactly 10 digits.
|
||||
NPI_OCR_PATTERN = r"\b[O0lI1S5G6B8gbo\d]{10}\b"
|
||||
NPI_OCR_PATTERN = r"\b(?:[O0lI1S5G6B8gbo\d]{10}[1lI])*[O0lI1S5G6B8gbo\d]{10}\b"
|
||||
|
||||
# OCR Substitution Mapping
|
||||
OCR_SUBSTITUTIONS = {
|
||||
|
||||
@@ -66,6 +66,22 @@ def get_all_matches_with_ocr(
|
||||
# Get OCR-correctable candidates (even if we found exact matches)
|
||||
ocr_candidates = get_all_matches(text, ocr_pattern)
|
||||
for candidate in ocr_candidates:
|
||||
|
||||
# Checks if length follows pattern: 10*N + (N-1) -> (len + 1) % 11 == 0
|
||||
if (
|
||||
identifier_type == "NPI"
|
||||
and len(candidate) > 10
|
||||
and (len(candidate) + 1) % 11 == 0
|
||||
):
|
||||
# Split into chunks of 10, skipping every 11th character (the separator)
|
||||
chunks = [candidate[i : i + 10] for i in range(0, len(candidate), 11)]
|
||||
for chunk in chunks:
|
||||
corrected, is_valid = attempt_ocr_correction(chunk, identifier_type)
|
||||
if is_valid and corrected not in seen_values:
|
||||
results.append((corrected, "OCR_CORRECTED"))
|
||||
seen_values.add(corrected)
|
||||
continue
|
||||
|
||||
logging.debug(f"OCR candidate for {identifier_type}: {candidate}")
|
||||
corrected, is_valid = attempt_ocr_correction(candidate, identifier_type)
|
||||
if is_valid and corrected not in seen_values:
|
||||
|
||||
Reference in New Issue
Block a user