Skip to content

Commit 88c34cb

Browse files
committed
Add documentation for deidentification
1 parent cb94971 commit 88c34cb

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Automatic Pixel Data De-identification
2+
3+
Karnak can automatically detect and mask sensitive patient data (PHI) that is
4+
*burned into* the DICOM pixel data (text overlays such as patient name,
5+
accession number, dates, etc.). Instead of defining mask rectangles by hand per
6+
station name, Karnak sends each image to an external **de-identification image
7+
API** that runs OCR, detects sensitive text, and returns the mask areas to apply.
8+
9+
This feature is an option of the **Clean Pixel Data** profile element.
10+
11+
---
12+
13+
## How it works
14+
15+
1. A destination uses a de-identification profile that contains a **Clean Pixel
16+
Data** element with automatic mask generation enabled.
17+
2. For every eligible instance (US, Secondary Capture, XC SOP classes, or any
18+
image flagged `BurnedInAnnotation`), Karnak extracts the pixel data and a set
19+
of sensitive tag values and sends them to the external API.
20+
3. The API returns one or more mask areas (rectangles, each with a color).
21+
Karnak draws them on the image before forwarding it to the destination.
22+
4. If the API detects no sensitive data, no mask is applied and the image is
23+
forwarded unchanged.
24+
25+
### Sensitive tags sent to the API
26+
27+
The values of the following tags are sent so the API can detect them in the
28+
image. No pixel data leaves Karnak beyond the single frame being analysed.
29+
30+
`AccessionNumber`, `InstitutionName`, `OperatorsName`, `PatientAge`,
31+
`PatientBirthDate`, `PatientID`, `PatientName`, `PatientSex`,
32+
`PerformingPhysicianName`, `PerformedProcedureStepID`,
33+
`ReferringPhysicianName`, `StudyDate`.
34+
35+
### Fail-closed behavior
36+
37+
When automatic mask generation is enabled and the API is **unreachable or
38+
returns an error**, Karnak produces **no mask**, and the instance is **not
39+
forwarded**. This prevents un-masked PHI from leaking to the destination if the
40+
service is down. Check the Karnak logs for the cause (client error, server
41+
error, or unreachable service).
42+
43+
> Note: when automatic mask generation is enabled, the statically configured
44+
> station-name masks are **not** used. Manual masks only apply when automatic
45+
> generation is disabled.
46+
47+
---
48+
49+
## Enabling the option in a profile
50+
51+
### Via the UI
52+
53+
1. Open the profile editor and add (or edit) a **Clean Pixel Data** element.
54+
2. Enable **Automatic masks generation**.
55+
3. Make sure the profile also contains the **DICOM basic profile** element.
56+
4. Save and assign the profile to the destination's de-identification project.
57+
58+
### Via a YAML profile
59+
60+
Set the `automaticMasksGeneration` argument to `"true"` on the
61+
`clean.pixel.data` element:
62+
63+
```yaml
64+
name: "Automatic Deidentification Karnak Profile"
65+
version: "1.0"
66+
minimumKarnakVersion: "0.9.2"
67+
profileElements:
68+
- name: "Clean pixel data"
69+
codename: "clean.pixel.data"
70+
arguments:
71+
automaticMasksGeneration: "true"
72+
- name: "DICOM basic profile"
73+
codename: "basic.dicom.profile"
74+
```
75+
76+
Reference profiles are provided under
77+
[`profils/`](../profils): `Automatic-Deidentification-Karnak-Profile.yml` and
78+
`Automatic-Deidentification-No-Mask-Karnak-Profile.yml`.
79+
80+
---
81+
82+
## Configuring the external API endpoint
83+
84+
Karnak calls the de-identification image API at the URL configured by the
85+
`DEIDENTIFY_IMAGE_URL` environment variable (default
86+
`http://localhost:8000`). It maps to the `karnak.deidentify-image.url` property
87+
in `application.yml`:
88+
89+
```yaml
90+
karnak:
91+
deidentify-image:
92+
url: ${DEIDENTIFY_IMAGE_URL:http://localhost:8000}
93+
```
94+
95+
| Variable | Default | Description |
96+
|----------|---------|-------------|
97+
| `DEIDENTIFY_IMAGE_URL` | `http://localhost:8000` | Base URL of the de-identification image API. |
98+
99+
The API contract is documented in
100+
[`src/main/resources/deidentification-api.yaml`](../src/main/resources/deidentification-api.yaml).
101+
102+
---
103+
104+
## Deploying the external de-identification service
105+
106+
The de-identification image API is a separate service. Deploy and run it so that
107+
it is reachable from Karnak at `DEIDENTIFY_IMAGE_URL`.
108+
109+
> Deployment guide of the de-identification image API: <https://github.com/nroduit/image-ocr-identifier>
110+
111+
### Standard deployment
112+
113+
1. Deploy the de-identification image API (see the repository linked above).
114+
2. Point Karnak to it by setting `DEIDENTIFY_IMAGE_URL` to the service base URL.
115+
3. Restart Karnak so the new configuration is picked up.
116+
117+
### Portable build
118+
119+
The portable package can start the de-identification service as a **sidecar**
120+
alongside Karnak. It is controlled in `run.cfg`:
121+
122+
```sh
123+
### Image Deidentification
124+
DEIDENTIFY_IMAGE_ENABLED=true
125+
DEIDENTIFY_IMAGE_URL=http://localhost:8000
126+
```
127+
128+
| Variable | Default | Description |
129+
|----------|---------|-------------|
130+
| `DEIDENTIFY_IMAGE_ENABLED` | `true` | Start the bundled de-identification sidecar with the portable package. Set to `false` to manage the service yourself. |
131+
| `DEIDENTIFY_IMAGE_URL` | `http://localhost:8000` | Base URL Karnak uses to reach the service. |
132+
133+
When enabled, `run.sh` starts the bundled binary
134+
(`deidentify-karnak/deidentify-karnak`) on launch and stops it on shutdown. If
135+
the binary is missing, the step is skipped and a message is logged.
136+
137+
---
138+
139+
## Troubleshooting
140+
141+
| Symptom | Likely cause | Action |
142+
|---------|--------------|--------|
143+
| Images with automatic masking are not forwarded | API unreachable or returning errors | Check the API is running and reachable at `DEIDENTIFY_IMAGE_URL`; inspect Karnak logs. |
144+
| `Cannot reach de-identification image API ...` in logs | Wrong URL or service down | Verify `DEIDENTIFY_IMAGE_URL` and service health. |
145+
| `SOP Instance UID ... does not match` in logs | API returned a response for a different instance | Verify the API version and that it echoes back the request `sop_instance_uid`. |
146+
| No mask applied although PHI is visible | API detected no sensitive text, or the tag values are absent from the metadata | Confirm the sensitive tags are populated in the source metadata. |
147+

0 commit comments

Comments
 (0)