Skip to content

Vision โ€” Prism

New in v0.1.5

The olaverse.vision module wraps the Prism family โ€” small, self-contained image-to-image models for upscaling, denoising, and steganography. None of these require African-language data; they're general-purpose image utilities that ship under the same SDK.

pip install olaverse[vision]

Each Prism model ships its own small model.py architecture file alongside the checkpoint on its Hugging Face repo (no standard transformers auto-class covers FSRCNN/LIIF/U-Net image codecs). Loading a Prism model downloads and executes that model.py from the corresponding olaverse/prism-* repo โ€” the same approach documented on each model card. All Prism repos are published by Olaverse under Apache-2.0.


PrismUpscaler โ€” Super-Resolution

Model Cards: olaverse/prism-upscaler-2x ยท olaverse/prism-upscaler-4x ยท olaverse/prism-upscaler-max

size= Model Architecture Scale
"2x" (default) prism-upscaler-2x FSRCNN (~25K params) Fixed 2x
"4x" prism-upscaler-4x FSRCNN (~25K params) Fixed 4x
"max" prism-upscaler-max LIIF (RRDB encoder + implicit MLP decoder) Any continuous resolution

The 2x/4x models are fixed-scale convolutional upscalers โ€” fast, single forward pass. max targets an exact output resolution (e.g. fitting a specific size) at a higher inference cost per pixel.

from olaverse import PrismUpscaler

# Fixed scale
upscaler = PrismUpscaler(size="2x")
upscaler.upscale("input.jpg").save("output.jpg")

# Arbitrary target resolution
upscaler_max = PrismUpscaler(size="max")
upscaler_max.upscale("input.jpg", target_size=(1024, 1024)).save("output.jpg")

All three were trained with realistic degradation (blur, sensor noise, JPEG re-compression) rather than plain bicubic downsampling โ€” built for real-world low-quality input, not just clean synthetic test images.

Known limitations

  • 4x over-smooths fine/curly hair and other high-frequency texture โ€” a consistent, known tradeoff at this scale, not an occasional artifact.
  • None of the three have been evaluated against standard academic benchmarks (Set5/Set14/BSD100/Urban100) โ€” comparisons on each model card are informal, single-image checks against a bicubic baseline.

olaverse.vision.PrismUpscaler

PrismUpscaler(size: str = '2x')

Image upscaling with the Prism family.

Models (size=): "2x" โ€” prism-upscaler-2x (fixed 2x, FSRCNN, ~25K params) "4x" โ€” prism-upscaler-4x (fixed 4x, FSRCNN, ~25K params) "max" โ€” prism-upscaler-max (any continuous target resolution, LIIF)

Requires: pip install olaverse[vision]

Quick start โ€” fixed scale: >>> upscaler = PrismUpscaler(size="2x") >>> upscaler.upscale("input.jpg").save("output.jpg")

Quick start โ€” arbitrary target resolution: >>> upscaler = PrismUpscaler(size="max") >>> upscaler.upscale("input.jpg", target_size=(1024, 1024)).save("output.jpg")

Methods:

load

load()

Download and load the model (runs once; cached after first call).

upscale

upscale(image: 'str | os.PathLike | Image.Image', target_size: tuple | None = None) -> 'Image.Image'

Upscale an image.

Parameters:

Name Type Description Default
image 'str | os.PathLike | Image.Image'

Path to an image file, or a PIL.Image.

required
target_size tuple | None

(width, height) โ€” required for size="max", ignored otherwise.

None

Returns:

Type Description
'Image.Image'

PIL.Image: the upscaled image.


PrismDenoiser โ€” Noise/Blur/Compression Removal

Model Card: olaverse/prism-denoiser

Removes Gaussian noise, blur, and JPEG-like compression artifacts using a compact U-Net. Useful as a standalone restoration tool or as pre-processing before other image tasks.

Output is always 128x128

Input is resized to 128x128 internally and the output is returned at that resolution โ€” a 640x480 photo comes back 128x128, not restored in place. This is a restoration model for small tiles, not a full-resolution filter. To restore a larger image, tile it yourself, or follow PrismDenoiser with PrismUpscaler(size="max") to get back to the target resolution.

from olaverse import PrismDenoiser

denoiser = PrismDenoiser()
denoiser.denoise("noisy.jpg").save("denoised.jpg")

Reduces, doesn't eliminate, noise

On complex, high-detail scenes (foliage, sky), denoising is genuinely effective (+3-4 dB PSNR in the model card's benchmarks) but typically incomplete โ€” some residual grain remains. On near-grayscale/texture-only images, the model can render a faint color tint that isn't in the original, since it was trained predominantly on full-color photos.

olaverse.vision.PrismDenoiser

PrismDenoiser()

Image restoration โ€” removes Gaussian noise, blur, and JPEG-like compression artifacts.

Wraps olaverse/prism-denoiser โ€” a compact U-Net trained with on-the-fly random degradation. Input is resized to 128x128 and the output is returned at that resolution, whatever the input size โ€” this restores small tiles, it is not a full-resolution filter. Reduces but does not fully eliminate noise on complex, high-detail scenes.

Requires: pip install olaverse[vision]

Quick start

denoiser = PrismDenoiser() denoiser.denoise("noisy.jpg").save("denoised.jpg")

Methods:

load

load()

Download and load the model (runs once; cached after first call).

denoise

denoise(image: 'str | os.PathLike | Image.Image') -> 'Image.Image'

Remove noise/blur/compression artifacts from an image.

Parameters:

Name Type Description Default
image 'str | os.PathLike | Image.Image'

Path to an image file, or a PIL.Image. Resized to 128x128.

required

Returns:

Type Description
'Image.Image'

PIL.Image: the denoised image, always 128x128 regardless of input size.


PrismSteganography โ€” Hide/Recover Messages

Model Card: olaverse/prism-steganography

Hides a recoverable message (up to 8 ASCII characters / 64 bits) inside a cover image imperceptibly, using a jointly-trained U-Net encoder / CNN decoder pair. A differentiable noise layer sits between them at train time (blur, sensor noise, JPEG-like compression, pixel dropout).

Save as PNG โ€” JPEG destroys the message

The hidden bits do not survive a real JPEG round-trip at any quality setting, including quality=100, and do not survive rescaling. Always write the stego image to a lossless format, and decode it at 128x128 without an intermediate resize.

from olaverse import PrismSteganography

steg = PrismSteganography()

stego_image = steg.hide("cover.jpg", "hi there")
stego_image.save("stego.png")   # PNG โ€” a .jpg save loses the message

steg.reveal(stego_image)
# โ†’ 'hi there'

Images are resized to 128x128 internally; longer messages are silently truncated to 8 characters. Capacity is read from the checkpoint's msg_bits config (currently 64 bits). Truncation is applied to the UTF-8 bytes, so a non-ASCII message can be cut mid-character and come back with replacement characters โ€” treat the channel as ASCII-only.

Measured robustness โ€” lossless only

Recovery is exact (100% bit-accuracy) in memory, through a PNG round-trip, and under mild additive noise (Gaussian ฯƒ=5). It collapses to chance under the two most common real-world transforms:

Condition Bit accuracy
In-memory / PNG round-trip 1.00
Gaussian noise, ฯƒ=5 1.00
JPEG, quality=100 0.48
JPEG, quality=95 0.45
JPEG, quality=75 0.42
Downscale to 64x64 and back 0.50

Whatever JPEG approximation was used in the training noise layer did not transfer to real JPEG encoding. Treat this as a lossless-channel watermark, not a distortion-robust one. No error-correction coding is applied on top of the raw bits โ€” applications that need near-100% reliability should add redundancy (e.g. a repetition or Hamming code) on top of the raw bit channel, and even that will not rescue a JPEG round-trip.

olaverse.vision.PrismSteganography

PrismSteganography()

Hide/recover a short recoverable message inside an image.

Wraps olaverse/prism-steganography โ€” a U-Net encoder / CNN decoder pair. Message capacity comes from the checkpoint's msg_bits config (currently 64 bits = 8 ASCII characters); longer input is silently truncated over UTF-8 bytes, so non-ASCII messages can be cut mid-character. Images are resized to 128x128.

Save stego images as PNG. The hidden bits survive a lossless round-trip and mild additive noise, but are destroyed by JPEG at any quality (including quality=100) and by rescaling โ€” recovery drops to chance.

Requires: pip install olaverse[vision]

Quick start

steg = PrismSteganography() stego_image = steg.hide("cover.jpg", "hi there") stego_image.save("stego.png") # PNG, not JPEG steg.reveal(stego_image) 'hi there'

Methods:

load

load()

Download and load the encoder/decoder pair (runs once; cached after first call).

hide

hide(image: 'str | os.PathLike | Image.Image', message: str) -> 'Image.Image'

Hide a short message inside a cover image.

Parameters:

Name Type Description Default
image 'str | os.PathLike | Image.Image'

Path to an image file, or a PIL.Image. Resized to 128x128.

required
message str

Up to 8 ASCII characters โ€” longer input is truncated.

required

Returns:

Type Description
'Image.Image'

PIL.Image: the stego image with the message hidden inside. Save it

'Image.Image'

losslessly (PNG); a JPEG save destroys the hidden message.

reveal

reveal(image: 'str | os.PathLike | Image.Image') -> str

Recover a hidden message from a stego image.

Parameters:

Name Type Description Default
image 'str | os.PathLike | Image.Image'

Path to an image file, or a PIL.Image. Must be a lossless copy of the stego image โ€” JPEG or rescaled input decodes to noise.

required

Returns:

Name Type Description
str str

the recovered message.