I am excited that the Halide developers have announced that Halide 19 will soon to be published on PyPI. Halide is a high-level image processing library with bindings in C++ and Python that we use in Zivid, where I work.

Halide 19 will be the first modern version of Halide to be hosted on PyPI. The current version is Halide 0.2 and was published in 2013.

I have been wanting to share more of what I have learned about Halide over the past years. With a Python package available, it will become so much easier to share examples for others to try out.

One of the things I have been testing recently is making interactive figures in Halide for the web. Since Halide pipelines can be defined in Python and compiled directly to WebAssembly, it is possible to run computationally heavy processing on a web page. Even with interactive updates.

Below is an example of such a visualization. It shows an image and allows you to darken it by adjusting a factor:

import halide as hl
import halide.imageio
from halide_widgets import Slider, interact

x = hl.Var("x")
y = hl.Var("y")
c = hl.Var("c")

image_data = halide.imageio.imread("river.jpg")
image_buffer = hl.Buffer(image_data)

image = hl.Func("image")
image[x, y, c] = image_buffer[x, y, c] / 255.0
factor = hl.Param(hl.Float(32), "factor", 1.5)

darken = hl.Func("darken")
darken[x, y, c] = image[x, y, c] / factor

slider = Slider(factor, min_value=1, max_value=10, step=0.1)
interact(
    darken,
    size=[image_buffer.width(), image_buffer.height(), 3],
    controls=[slider],
)


Darken factor: 1.5

If you move the slider, you can see the effect instantaneously.

The halide_widgets library is a small helper utility I made mainly to enable such interactive figures on webpages about Halide. However, since all it does is generate HTML, WebAssembly and JavaScript, it also works for creating interactive figures as part of a Jupyter Notebook.

Compiling the Halide Func to WebAssembly, linking with Emscripten, and loading the module in the browser takes a bit of time, but once everything is loaded the interactive plot is pretty responsive.

Here is another example visualizing a 2D function:

import halide as hl
from halide_widgets import Slider, interact
from halide import cos, sqrt, sin, atan2

width = 240
height = 120

x = hl.Var("x")
y = hl.Var("y")

xx = (x - hl.f32(width) / 2.0) / (hl.f32(width))
yy = (y - hl.f32(height) / 2.0) / (hl.f32(width))

a = hl.Param(hl.Float(32), "a", 4.0)
b = hl.Param(hl.Float(32), "b", 1.0)
c = hl.Param(hl.Float(32), "c", 1.0)
d = hl.Param(hl.Float(32), "d", 1.0)

r = sqrt(xx**2.0 + yy**2.0)
theta = atan2(xx, yy)

waves = hl.Func("waves")
waves[x, y] = (sin(a * theta + c) + b * cos(d * r))

interact(
    waves,
    size=[width, height],
    controls=[
        Slider(a, 0.0, 36.0, 1.0),
        Slider(b, 0.0, 10.0, 0.01),
        Slider(c, 0.0, 10.0, 0.01),
        Slider(d, 0.0, 100.0, 0.01),
    ],
)


a: 36

b: 1.5

c: 1.5

d: 1.5

The halide_widgets library is currently very experimental and assumes that you for instance have Emscripten installed and available in PATH. I do not have any big plans for the library, but will use it for some of my own projects. So while I cannot give any promises for its continued maintenance, I will probably update it with some more features in the future.

While halide_widgets is published already, it will not work until Halide 19 is on PyPI as well. However, you can configure your setup to use test.pypi.org, but I would recommend just waiting for Halide 19.