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​