Deck.gl: Bitmap layer using pydeck with DataFrame

Created on 7 Nov 2020  路  6Comments  路  Source: visgl/deck.gl

Is there a way to pass a Pandas DataFrame (or numpy arrray) to PyDeck Bitmap layer to render as an image?

I would like to do something like this

array = np.zeros([100, 200, 4], dtype=np.uint8)
array[:,:100] = [255, 100, 0, 255] 
array[:,100:] = [0, 0, 255, 255]   

import pydeck as pdk

bitmap_layer = pdk.Layer("BitmapLayer", data=array,  opacity=0.7)

r = pdk.Deck(bitmap_layer)

r.show()

I am able to plot the values of a matrix (where each row represents the lng-lat value of a matrix) using the GridCellLayer but I'm wondering whether the Bitmap layer would work better

grid_layer = pdk.Layer(
    "GridCellLayer",
    df,
    pickable=True,
    cell_size=ini_cell_size,
    get_position=['lng', 'lat'],
    extruded=False,
    get_fill_color = 'color',    
)
pydeck question

All 6 comments

The BitmapLayer is indeed more suitable for this use case.

In JavaScript you can pass a ImageData object to the image prop:

new BitmapLayer({
  // ...
  image: new ImageData(<Uint8ClampedArray>, width, height)
})

I think pydeck may need some modifications to support this?
@ajduberstein @ibgreen

Thanks for the question @cornhundred. You can do this in pydeck鈥揻irst convert the matrix to an image and then convert the image to a base64-encoded string. See this Stack overflow question on converting a numpy matrix to an image and then you can convert that image to a base64-encoded string.

Thanks @ajduberstein and @Pessimistress, I tried the following using the red dot and it worked

red_dot_url = '"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="'

Screen Shot 2020-11-09 at 9 58 13 PM

but I was unable to visualize a custom image (blue square)

w, h = 20, 20
data = np.zeros((h, w, 3), dtype=np.uint8)
data[0:25, 0:25] = [0, 0, 255] # red patch in upper left
img = Image.fromarray(data, 'RGB')

blue_square_url = '"data:image/png;base64,'+ str(base64.b64encode(img.tobytes()).decode('utf-8')) + '"'

The blue square url is

'"data:image/png;base64,AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/"'

The following just showed a white background

# base64-encoded image string of a red dot
bitmap_layer = pdk.Layer("BitmapLayer", data=None, image=blue_square_url, opacity=1.0)
view_state = pdk.ViewState(longitude=0.5, latitude=0.5, zoom=7)
r = pdk.Deck(bitmap_layer, initial_view_state=view_state)
r.show()

Copying and pasting this into the browser (as recommended by https://github.com/visgl/deck.gl/issues/4977#issuecomment-700118566) showed a black square so I'm guessing the encoding failed.

Thanks @ajduberstein, that worked. Although, I had to strip off a few characters from the str(img_str)[2:1]

from io import BytesIO

buffered = BytesIO()
img.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue())
str(img_str)

new_blue_square_url = '"data:image/png;base64,'+ str(img_str)[2:-1] + '"'
new_blue_square_url

which gives

'"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAHUlEQVR4nGNkYPjPQC5gIlvnqOZRzaOaRzVTRTMAIJ4BJ6WiocQAAAAASUVORK5CYII="'

Screen Shot 2020-11-09 at 10 46 48 PM

@ajduberstein one more quick question, is there a way to prevent the apparent anti-aliasing that blurs the image?
Screen Shot 2020-11-09 at 11 22 31 PM

Was this page helpful?
0 / 5 - 0 ratings