Skip to main content

Quick Start

Protect an image

import safelicensing as sl
from PIL import Image

model = sl.load_model() # loads bundled best.pt

image = Image.open("car.jpg")
result = sl.protect_image(image, seed=0.42, model=model)

result.original.show() # original, unmodified
result.detected.show() # red bounding boxes
result.encrypted.save("car_protected.jpg") # plate regions encrypted

print(f"Plates found : {len(result.bboxes)}")
print(f"Elapsed : {result.elapsed:.2f}s")

What protect_image returns

protect_image returns a ProtectImageResult dataclass:

FieldTypeDescription
originalPIL.ImageUnmodified RGB input
detectedPIL.ImageInput with red bounding boxes
encryptedPIL.ImageFull image with plate regions encrypted
bboxeslist[tuple](x1, y1, x2, y2) per detected plate
elapsedfloatWall-clock processing time (seconds)

Protect a video

import safelicensing as sl

model = sl.load_model()

result = sl.protect_video(
"dashcam.mp4",
seed=0.42,
model=model,
output_path="dashcam_protected.mp4",
progress_callback=lambda p: print(f"\r{p:.0%}", end=""),
)

print(f"\nOutput : {result.output_path}")
print(f"Frames : {result.frame_count}")
print(f"FPS : {result.fps:.2f}")
print(f"Elapsed : {result.elapsed:.2f}s")

What protect_video returns

protect_video returns a ProtectVideoResult dataclass:

FieldTypeDescription
output_pathstrAbsolute path to the encrypted video
frame_countintTotal frames processed
fpsfloatOutput frame rate
elapsedfloatWall-clock processing time (seconds)

Launch the Streamlit UI

safelicensing

Opens http://localhost:8501. Upload images or videos, adjust the encryption seed, and download protected output directly from the browser.


Batch processing

import safelicensing as sl
from pathlib import Path
from PIL import Image

model = sl.load_model() # load once, reuse across all images

for path in Path("images/").glob("*.jpg"):
result = sl.protect_image(Image.open(path), seed=0.5, model=model)
result.encrypted.save(f"output/{path.stem}_protected.jpg")
print(f"{path.name}: {len(result.bboxes)} plates, {result.elapsed:.2f}s")

Custom model

Bring your own YOLOv8 weights trained for license plate detection:

model = sl.load_model("path/to/my_model.pt")
result = sl.protect_image(image, seed=0.5, model=model)

Next steps