Download paddle/code/trocr_character_codec.py from ampixa/deva-ocr-75m-research: direct link, hf CLI and curl.
- Browser
- Download file 2.23 kB
-
https://huggingface.co/ampixa/deva-ocr-75m-research/resolve/main/paddle/code/trocr_character_codec.py
- Command line
-
hf download hf://ampixa/deva-ocr-75m-research/paddle/code/trocr_character_codec.py
-
curl -L -o trocr_character_codec.py https://huggingface.co/ampixa/deva-ocr-75m-research/resolve/main/paddle/code/trocr_character_codec.py
2.23 kB
| """Literal NFC character codec for the experimental compact TrOCR decoder. | |
| Tokenizer BOS0 is serialization only; training targets exclude it. Generation | |
| starts with EOS2 and suppresses BOS/PAD/UNK. Unknown outputs remain visible as | |
| replacement characters when decoded, never silently removed. | |
| """ | |
| import unicodedata | |
| class CharacterCodec: | |
| def __init__(self, characters): | |
| if len(characters) != len(set(characters)) or any(len(c) != 1 for c in characters): | |
| raise ValueError('Require ordered, unique Unicode codepoints') | |
| self.characters = list(characters) | |
| self.native = set(characters) | |
| self.character_ids = {c: i + 4 for i, c in enumerate(characters)} | |
| self.id_characters = {i: c for c, i in self.character_ids.items()} | |
| self.classes = len(characters) + 4 | |
| def encode(self, text): | |
| if not text or text != unicodedata.normalize('NFC', text).strip(): | |
| raise ValueError('Require nonempty, stripped NFC text') | |
| if any(c not in self.native for c in text): | |
| raise ValueError('Text outside the fixed OCR alphabet') | |
| return [0, *[self.character_ids[c] for c in text], 2], 'characters' | |
| def decode(self, ids): | |
| pieces = [] | |
| for index in ids: | |
| if index in [0, 1, 2]: | |
| continue | |
| if index == 3: | |
| pieces.append('\ufffd') | |
| elif index in self.id_characters: | |
| pieces.append(self.id_characters[index]) | |
| else: | |
| raise ValueError('Unassigned character output ID') | |
| return unicodedata.normalize('NFC', ''.join(pieces)) | |
| def manifest(self): | |
| return {'version': 1, 'kind': 'literal_NFC_characters', 'classes': self.classes, | |
| 'special_ids': {'BOS_serialization': 0, 'PAD': 1, 'EOS_and_decoder_start': 2, 'UNK': 3}, | |
| 'character_ids': self.character_ids, 'generation_suppressed_ids': [0, 1, 3], | |
| 'training_target': 'Drop serialization BOS0 only; retain every text codepoint and EOS2', | |
| 'unknown_output': 'Decode3 as U+FFFD, never silently remove it', | |
| 'scope': 'Experimental codec, not recognition quality or Paddle qualification.'} | |