Image slider in Dash

Hi all,
I am starting to use dash and I want to build an application where I can compare two images using a slider. The effect is sometimes called before-after here is an example:

would you have any idea on how to implement this using dash?

Thanks!

I don’t think there are any components available, but it should be relatively easy to port a react component, e.g this one

Thanks @Emil do you have any tutorial where it is explained how to do this porting?
I only python but maybe can give it a try.

Here is an example of one of the simpler components that i have made,

Have you figured out which react component to port yet?

1 Like

The one you showed seems good, the only thing is that I would like to pass images as numpy arrays as opposed to pngs or jpgs like in here:
html.Img | Dash for Python Documentation | Plotly
I was checking your code but it seems that to be simple it needs to exist a very close component otherwise it would be more difficult I suppose.

Yes, the closer to the react component, the easier. For your usecase, you could save the numpy arrays as images in a hosted folder, and set urls to these images as the properties of the before-after-slider.

I figured this kind of component is actually pretty neat, so i just made a quick implementation. Here is a small example,

import dash_html_components as html
import numpy as np

from dash import Dash
from dash_extensions import BeforeAfter
from PIL import Image


def make_image(label):
    data = np.random.random((width, height))
    rescaled = (255.0 / data.max() * (data - data.min())).astype(np.uint8)
    Image.fromarray(rescaled).save(f'assets/{label}.png')
    return f"assets/{label}.png"


width, height = 800, 600
app = Dash(prevent_initial_callbacks=True)
app.layout = html.Div([
    BeforeAfter(before=make_image("before"), after=make_image("after"), width=width, height=height)
])

if __name__ == '__main__':
    app.run_server()

It requires the latest rc version of dash-extensions,

pip install dash-extensions==0.0.47rc4

Peek 2021-03-17 22-06

5 Likes

wow this is really awesome! Thank you very much for sharing!
in your implementation is it possible to change the before and after images dynamically? like on a callback?

Yes, they are just like any other dash props. You can pass in an url to any hosted image; also via callbacks :slight_smile:

Thanks @Emil !
I am running it and it works out of the box :slight_smile:
I modified a little so that the code will modify the images each time I press a button. My code looks like this:

import dash_html_components as html
import numpy as np

from dash import Dash
from dash_extensions import BeforeAfter
from PIL import Image

import dash


def make_image(label):
    data = 255*np.random.random((width, height, 3))
    data = data.astype(np.uint8)

    # rescaled = (255.0 / data.max() * (data - data.min())).astype(np.uint8)
    if label == 'after':
        data[...] = (255*np.random.rand(3)).astype(np.uint8)
    Image.fromarray(data).save(f'assets/{label}.png')
    return f"assets/{label}.png"


width, height = 800, 600
app = Dash(prevent_initial_callbacks=True)
app.layout = html.Div([html.Div(id='slider', children=[
    BeforeAfter(before=make_image("before"), after=make_image(
        "after"), width=width, height=height)]),

    html.Div([html.Button('Submit', id='submit-val', n_clicks=0)])])


@app.callback(
    dash.dependencies.Output('slider', 'children'),
    dash.dependencies.Input('submit-val', 'n_clicks'))
def update_output(n_clicks):
    out = BeforeAfter(before=make_image("before"), after=make_image(
        "after"), width=width, height=height)
    return out


if __name__ == '__main__':
    app.run_server()

The code is working because I can see the images being modified; however they are not updated in the website. Am I doing something wrong?
Thanks again awesome contribution!

1 Like

seems the browser was caching the images, the solution I found was to add random strings to the name of the images

Will this component eventually make it to a subsequent dash-extensions major version?

Yes. I hope to release it today. Stay tuned (:

I have just release version 0.0.47, which includes the BeforeAfter component. I have also added a small example to the docs,

import dash_html_components as html
from dash import Dash
from dash_extensions import BeforeAfter

app = Dash()
app.layout = html.Div([
    BeforeAfter(before="assets/lena_bw.png", after="assets/lena_color.png", width=512, height=512)
])

if __name__ == '__main__':
    app.run_server()

Peek 2021-03-21 10-20

2 Likes

Beautiful work @emil! :heart_eyes_cat:

2 Likes