Blur immodestly dressed people in videos. Video in, video out.
Project description
OCCLUDE
As a muslim, there is content I want to watch and don't. Not because it's bad content (documentaries, lectures, educational videos I'm genuinely curious about), but because they have immodestly dressed people in them, and I'd rather not sit through that. The friction is not the content, it's what's mixed into it.
I went looking for a tool that would just take the video and give me back the same video, with those people blurred. Browser extensions like HaramBlur and PordaAI process in real time, which forces brutal accuracy tradeoffs: flickering, missed frames, false positives. I needed something for offline processing, where you trade interactivity for actually getting it right.
OCCLUDE is what I built. You give it a video file, it gives you back a video file, the immodestly dressed people are blurred according to Islamic modesty rules, and the original audio is intact.
occlude --input documentary.mp4
# → documentary_occluded.mp4
This is not a general people-removal or object-removal tool. The blur logic checks what's visible on each person against specific Islamic modesty criteria, not just whether someone is present. I built it for muslims who run into the same friction. If that's you, you're welcome here.
The modesty rules
The decision is binary: a person either gets fully blurred or they don't. There's no partial blur of a specific body part.
For women, the entire person is blurred if any of the following is visible: uncovered hair, bare arms, bare legs, or exposed neck and chest. Uncovered hair is the primary trigger in practice: if hair is visible, the person is blurred.
For men, the entire person is blurred if any skin in the zone between the navel and the knee is visible. Being shirtless is the primary trigger since it automatically exposes the navel. Shorts or exposed thighs are the secondary case.
People dressed modestly are never blurred: a woman in full hijab and modest clothing, a man in a t-shirt and full-length trousers. Faces of modestly dressed people, backgrounds, objects, animals, and text overlays are not touched.
How it works
input.mp4 ─▶ frame extraction
│
person detection (YOLOv8)
│
gender classification (per person)
│
body part segmentation (per person crop)
│
modesty rule check (binary decision)
│
blur full bounding box if triggered
│
temporal smoothing (carry flag across frames)
│
video reconstruction (original audio preserved)
│
output_occluded.mp4
YOLOv8 finds the people. A gender classifier determines which rule set applies. A body-part segmentation model identifies what's visible on each crop. The modesty rules run on that output, and if triggered, the full bounding box gets a Gaussian blur. Basic tracking carries a flag forward a few frames so the blur doesn't flicker when detection briefly drops between frames.
Install
pip install occlude
If you have an NVIDIA GPU, install the GPU extra instead. It pulls in onnxruntime-gpu so the face and gender model runs on CUDA along with everything else, which is the difference between a long file finishing overnight and finishing while you sleep badly:
pip install 'occlude[gpu]'
Python 3.10+ required. I develop on macOS with Apple Silicon, and for anything long I run the CUDA path, usually on Google Colab. Plain CPU works but gets slow fast on anything past a short clip.
Usage
occlude --input /path/to/video.mp4
Output is saved in the same directory as the input, named video_occluded.mp4.
Optional flags:
occlude --input video.mp4 --output cleaned.mp4 # custom output path
occlude --input video.mp4 --blur-strength 99 # Gaussian kernel size, odd number (default 199)
occlude --input video.mp4 --frame-stride 3 # run detection every 3rd frame
--frame-stride is the one that matters for long content. On the frames it skips it doesn't re-run detection, it just re-applies the previous frame's blur, so a stride of 3 is roughly three times faster for a small amount of positional lag the soft blur edge hides anyway. I run feature-length files at stride 3 to 6. Leave it at 1 if you want every frame analysed and don't mind the wait.
Running on Google Colab
OCCLUDE is compute-intensive, and where it runs changes the experience a lot. On an NVIDIA GPU every stage runs on CUDA: person detection, body-part segmentation, the per-frame blur, and the face and gender model. On Apple Silicon the detector and segmenter use the GPU through Metal, but the face and gender model still falls back to the CPU, so a feature-length file is slow even there. On a plain CPU it gets painful well before you reach a documentary.
So for anything long, Google Colab with a GPU runtime is the path I actually use. A ready-to-run notebook is at notebooks/occlude_colab.ipynb. Open it in Colab, point it at your video, and run the cells. The notebook installs occlude[gpu], repairs the onnxruntime-gpu install so the face model doesn't silently land on the CPU, and verifies every stage is on the GPU before it starts a multi-hour run.
What OCCLUDE isn't
Before you install it, a few things it doesn't do, so you don't find out the wrong way.
It's not a general people-removal or object-removal tool. If you want to blur all people regardless of dress, or remove specific objects, this is the wrong tool. The blur is tied to the modesty rules above and only triggers when they're violated.
It's not a browser extension and doesn't do real-time processing. OCCLUDE works on local video files only.
It's terminal only. No GUI, no drag-and-drop.
It doesn't take YouTube URLs or download videos. Give it a local file.
Development stage
It works and I use it on real content, but it's still early. The accuracy is reasonable on clear cases: shirtless men, women with uncovered hair and bare arms in decent lighting. Edge cases will give you trouble: unusual angles, partial occlusion, low-resolution video, complex backgrounds.
A long documentary on a machine without GPU acceleration will take a while. Start with a short clip to confirm the output is what you need before committing to a full-length file.
If you find a consistent failure mode, open an issue with a description of the content type. That's more useful than a general accuracy complaint.
Contributing
The parts most worth improving right now: segmentation accuracy, gender classification on difficult crops, and speed on long content. NVIDIA is covered now through the CUDA path; AMD and other accelerators aren't yet. If you want to build a frontend or optimise for a different hardware target, there's room for that too.
Open an issue or PR at https://github.com/anaxoniclabs/OCCLUDE/issues.
If a fellow muslim developer takes this further than I could, that's honestly the outcome I'd be happiest with.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file occlude-1.1.4.tar.gz.
File metadata
- Download URL: occlude-1.1.4.tar.gz
- Upload date:
- Size: 39.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fdddf3e311b689e590e1b01df860f40cd7d83a742e4200162bcbd4ac1319d7b
|
|
| MD5 |
99ae37fb29fb57c84209a3e1524a43d1
|
|
| BLAKE2b-256 |
6481a025169daa9d4748979fe4cd00be5d82413d6f72be29ab30dac0fd7460d4
|
Provenance
The following attestation bundles were made for occlude-1.1.4.tar.gz:
Publisher:
publish.yml on anaxoniclabs/OCCLUDE
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
occlude-1.1.4.tar.gz -
Subject digest:
0fdddf3e311b689e590e1b01df860f40cd7d83a742e4200162bcbd4ac1319d7b - Sigstore transparency entry: 1574393910
- Sigstore integration time:
-
Permalink:
anaxoniclabs/OCCLUDE@ac58b20990c67a74456c57ab667d7cafdbe61c54 -
Branch / Tag:
refs/tags/v1.1.4 - Owner: https://github.com/anaxoniclabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ac58b20990c67a74456c57ab667d7cafdbe61c54 -
Trigger Event:
release
-
Statement type:
File details
Details for the file occlude-1.1.4-py3-none-any.whl.
File metadata
- Download URL: occlude-1.1.4-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c2983c43f23d14dbf082352a5f242b5ed533ba04b718e2125d579a21d2aa8b2
|
|
| MD5 |
afc16627089b422cbb5e57d409b7d096
|
|
| BLAKE2b-256 |
68d01b5d1bd1d0cfb69f18be47fe60985568bd5d23bb18b2003fee07ce2699af
|
Provenance
The following attestation bundles were made for occlude-1.1.4-py3-none-any.whl:
Publisher:
publish.yml on anaxoniclabs/OCCLUDE
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
occlude-1.1.4-py3-none-any.whl -
Subject digest:
0c2983c43f23d14dbf082352a5f242b5ed533ba04b718e2125d579a21d2aa8b2 - Sigstore transparency entry: 1574393964
- Sigstore integration time:
-
Permalink:
anaxoniclabs/OCCLUDE@ac58b20990c67a74456c57ab667d7cafdbe61c54 -
Branch / Tag:
refs/tags/v1.1.4 - Owner: https://github.com/anaxoniclabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ac58b20990c67a74456c57ab667d7cafdbe61c54 -
Trigger Event:
release
-
Statement type: