File size: 8,535 Bytes
3d54166
43cecc2
 
444252f
f7d44f2
3d54166
 
444252f
3d54166
849a001
c088fc4
849a001
 
 
 
e83dc6e
 
 
 
eccf8ce
 
 
 
 
1d2966f
 
e83dc6e
444252f
 
 
d491ab8
3d54166
f7d44f2
2f4478b
f7d44f2
3d54166
f7d44f2
 
2f4478b
 
 
 
028db69
 
2f4478b
 
58ee8c9
 
 
 
 
93d8fcf
7d39f6d
 
 
f0e1525
 
 
 
 
 
 
3d54166
 
 
c9dd10d
206255b
 
 
2f4478b
3d54166
206255b
2f4478b
206255b
 
 
c9dd10d
206255b
 
580620f
 
7d39f6d
206255b
 
 
3d54166
2f4478b
206255b
2f4478b
 
206255b
2f4478b
206255b
 
 
2f4478b
206255b
 
 
 
 
 
 
2f4478b
580620f
206255b
2f4478b
 
206255b
 
 
 
 
 
 
b1d2a7f
 
206255b
 
55ff413
206255b
 
b1d2a7f
206255b
 
b1d2a7f
 
206255b
 
 
 
 
 
 
 
 
 
b1d2a7f
206255b
1d2966f
 
 
206255b
 
1c00698
 
 
43cecc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444252f
1c00698
 
 
 
444252f
1c00698
206255b
1c00698
 
444252f
 
1c00698
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
---
license: other
license_name: per-model-licenses
license_link: https://huggingface.co/ekacare/document-pii-redactor#license-and-attribution
tags: [pii, redaction, document-ai]
---

# document-pii-redactor model weights

**Try it live:** [medai.eka.care/pii-redactor](https://medai.eka.care/pii-redactor)
(faster), or the [Hugging Face Space](https://huggingface.co/spaces/ekacare/document-pii-redactor)
β€” upload a document image or paste text and see detection + redaction run
in your browser. Background and design notes are in the
[launch blog](https://info.eka.care/services/releasing-parrotlet-open-models-open-weights-for-medical-document-intelligence).

Most PII redactors stop at plain text. These models power
[document-pii-redactor](https://github.com/eka-care/document-pii-redactor),
which also redacts **document images** and is light enough to deploy on
**CPU**. They are trained to understand **Indian names, documents, and
contexts**, and the text model works across **Indian languages**. The main
contribution is the **PII token classifier** β€” OCR is just the pluggable
input stage in front of it. It defaults to lightweight **Tesseract**, which
keeps memory low and works well for PDFs and good-quality images; for more
difficult or blurred images, **Bring-your-own OCR** lets a model like [**Nemotron OCR**](https://huggingface.co/nvidia/nemotron-ocr-v2) (or
Textract, Google Vision, etc) plug straight in for better results
([example notebook](https://github.com/eka-care/document-pii-redactor/blob/main/examples/byo_ocr_nemotron.ipynb)).

Single repo holding the models used by the document-pii-redactor GitHub repo
(https://github.com/eka-care/document-pii-redactor), organized by modality. You
can use the document-pii-redactor repo directly to use these models β€” it has
the library, a Docker image, and a FastAPI server.

- `image/layoutlmv3/` β€” a text-in-image classifier for **text PII in
  images** (47 categories), run on Tesseract OCR words.
- `image/yolo/best.pt` β€” a detector for **visual entities** (signature,
  seal/stamp, QR/barcode, face photo, fingerprint, logo).
- `text/minilm/` β€” a lightweight multilingual classifier for **PII in
  plain text** (no image, no OCR).

## Install

```bash
pip install "document-pii-redactor[visual]"  # full pipeline, used by the examples below (AGPL-3.0 β€” see License below)
pip install document-pii-redactor            # text pipeline + built-in OCR only, no visual entities (permissive licenses)
```

`ImagePIIRedactor` detects **visual entities** by default β€” PII that is an
image region rather than readable text: signatures, seals/stamps,
QR codes/barcodes, face photos, fingerprints, and logos. That detector
needs the `[visual]` extra, so the image examples below assume it β€” or
pass `detect_visual=False` to detect only text PII on the core install.

System dependency: **Tesseract OCR** β€” used by the **image** modality's
built-in OCR step. Not needed for the text-only modality, nor if you bring
your own OCR (`detect(..., words=..., boxes=...)`).

```bash
# Debian/Ubuntu
sudo apt-get install -y tesseract-ocr
# macOS
brew install tesseract
```

## Usage

**`detect()` is the core primitive** β€” it finds every PII entity with its
location, category, and confidence, and runs the models exactly once. The
transforms (redact / anonymize / de-identify) take its result as a required
argument: detect once, feed the result to any transform.

```python
from document_pii_redactor import ImagePIIRedactor, TextPIIRedactor

image_redactor = ImagePIIRedactor("ekacare/document-pii-redactor")
entities = image_redactor.detect("page.jpg")   # built-in Tesseract OCR
# each entity: kind ("text"/"visual"), category, bbox (pixels), text, score

# …or bring your own OCR β€” pass words + pixel boxes, Tesseract is skipped
# and your exact boxes come back on the detected entities:
entities = image_redactor.detect("page.jpg", words=["John", "Doe"],
                                 boxes=[[100, 20, 140, 40], [145, 20, 180, 40]])

text_redactor = TextPIIRedactor("ekacare/document-pii-redactor")
text  = "Mr. John Doe, 45 yrs, DOB 12-03-1979, Indiranagar, Bangalore. Contact: +91 98765 43210."
spans = text_redactor.detect(text)             # char-offset spans
```

**Redact** β€” destroy:

```python
image_redactor.redact("page.jpg", entities, mode="blur").save("redacted.png")  # or "solid" / "pixelate"

text_redactor.redact(text, spans)
# '[REDACTED], [REDACTED] yrs, DOB [REDACTED], [REDACTED], [REDACTED]. Contact: [REDACTED].'
```

**Anonymize** β€” generalize, one-way, no mapping kept. Ages become 10-year
buckets, dates keep only the year, fine geography collapses to `[LOCATION]`
(state and country survive), everything else becomes an unnumbered token;
faces/signatures are filled solid:

```python
image_redactor.anonymize("page.jpg", entities).save("anonymized.png")

text_redactor.anonymize(text, spans)
# '[PERSON], 40–49 yrs, DOB 1979, [LOCATION], [LOCATION]. Contact: [PHONE].'
```

**De-identify** β€” pseudonymize. Same value β†’ same pseudonym throughout the
document (rendered in place in images; faces/signatures become neutral
placeholders), and the entity→pseudonym mapping comes back for authorized
re-linking β€” yours to store securely, never persisted by the library.
`strategy="hash"` gives globally deterministic tokens that stay stable across
documents with no mapping to thread (`secret=` salts the hash so guessable
values can't be dictionary-reversed):

```python
deid = image_redactor.deidentify("page.jpg", entities)    # .image + .mapping
deid.image.save("deidentified.png")

text_redactor.deidentify(text, spans).text
# 'Person_1, Age_1 yrs, DOB Date_1, City_1, City_2. Contact: Phone_1.'

text_redactor.deidentify(text, spans, strategy="hash").text
# 'Person_539681, Age_6c8349 yrs, DOB Date_7f19c4, City_d12704, City_60c7d5. Contact: Phone_d57003.'
```

Good to know:

- `categories=[...]` on `detect()` limits which of the 53 PII categories are
  found (default: all); `detect_visual=False` on `ImagePIIRedactor` skips the
  visual-entity detector entirely.
- Sequential pseudonyms are scoped to the returned `mapping` β€” pass
  `mapping=result.mapping` on the next page of the same record to keep
  numbering consistent. Hash tokens need no threading.
- Anonymization is best-effort removal/generalization of detected
  identifiers β€” not a k-anonymity guarantee or a compliance determination.

See the [document-pii-redactor GitHub repo](https://github.com/eka-care/document-pii-redactor)
for runnable notebook walkthroughs β€”
[`quickstart.ipynb`](https://github.com/eka-care/document-pii-redactor/blob/main/examples/quickstart.ipynb) and
[`byo_ocr_nemotron.ipynb`](https://github.com/eka-care/document-pii-redactor/blob/main/examples/byo_ocr_nemotron.ipynb) β€” the full
API reference, the category taxonomy, and the Docker/FastAPI deployment setup
(the same setup behind the demo Space above).

## License and attribution

The weights are licensed **per model**, following each base model's
license (a fine-tune is a derivative of its base β€” the base license
flows through):

| weights | fine-tuned from | license |
|---|---|---|
| `text/minilm/` | Multilingual MiniLM (MIT) | **CC-BY-4.0** β€” free use incl. commercial; credit Eka Care with a link back |
| `image/layoutlmv3/` | [microsoft/layoutlmv3-base](https://huggingface.co/microsoft/layoutlmv3-base) (CC-BY-NC-SA-4.0) | **CC-BY-NC-SA-4.0** β€” **non-commercial use only**, ShareAlike |
| `image/yolo/best.pt` | YOLO11m ([Ultralytics](https://github.com/ultralytics/ultralytics), AGPL-3.0) | **AGPL-3.0** |

Practical summary: the **plain-text pipeline (`TextPIIRedactor`) has a
fully permissive lineage** and may be used commercially with attribution.
The image pipeline currently inherits its bases' restrictions β€” no
commercial use of the LayoutLMv3 fine-tune, and AGPL obligations for the
visual detector (the `ultralytics` runtime it needs is also AGPL-3.0 and
is an optional `[visual]` extra of the pip package).

The library code is Apache-2.0 at
https://github.com/eka-care/document-pii-redactor.

If you use the models or the library, please cite:

```bibtex
@software{document_pii_redactor,
  author = {{Eka Care}},
  title  = {document-pii-redactor: detect, redact, de-identify, or anonymize
            PII in document images and plain text},
  year   = {2026},
  url    = {https://github.com/eka-care/document-pii-redactor},
  note   = {Model weights: https://huggingface.co/ekacare/document-pii-redactor}
}
```