Applying full color image texture to create an interactive earth globe

@crgnam
Very interesting idea!!! <3
If colormapping were performed for surfaces, just like for heatmaps, then we could map an image as a texture for surfaces.
Three years ago, when px.imshow() didnโ€™t exist yet, I tried to learn from an image, via scikit learn KMeans, an array, z_data,
and a colorscale, to reproduce the image as a heatmap. The result was unexpectedly good (see
https://chart-studio.plotly.com/~empet/15173. )

Yesterday seeing your example I tried the same method to get (learn) from a RGB-image, the surfacecolor and the colorscale for a surface.
But the result is far from acceptable.
For comparison:

  • this is the original image:

sun-flower

  • and this one is the corresponding heatmap, plotted for z_data and colorscale returned by the function image2zvals defined in the Jupyter Notebook from my chart studio account (link posted above).
#img: https://github.com/empet/Datasets/blob/master/Images/sun-flower.jpg
z_data, colorscale = image2zvals(img, n_colors=64, n_training_pixels=5000)

image-as-heatmap
The number of colors in the colorscale can appear big, compared to the usual number of colors in a plotly.py colorscale, but it isnโ€™t. The Julia version, PlotlyJS.jl, passes colorscales for heatmaps, surfaces, etc, of 256 colors, similar to matplotlib colormaps.

Now trying to map the same z_data as texture (surfacecolor) for a surface, we get a surface with artifacts. It seems that interpolation isnโ€™t performed as for heatmaps :frowning:
Maybe @alexcjohnson and/or @archmoj could explain this odd behaviour.

The code for surface:

x= np.linspace(-pi, pi, c)  # r x c is the image resolution
y= np.linspace(-pi, pi, r)
x, y = np.meshgrid(x,y)
z= 0.5*cos(x/2) + 0.2*sin(y/4)
z_data, pl_colorscale = image2zvals(img1, n_colors=64, n_training_pixels=5000)
fig2 = go.Figure(go.Surface(x=x, y=y, z=z, surfacecolor=z_data,
                 colorscale=pl_colorscale,
                 showscale=False))
fig2.update_layout(width=650, height=650, font_size=11,
                   scene=dict(xaxis_visible=False, yaxis_visible=False,  zaxis_visible=False,
                           aspectmode="data", camera_eye=dict(x=2.5, y=2.5, z=1.5)))

As we decrease the number of colors (in fact k from 2^k, for KMeans) we get a better plot for surface:

Number of colors:

8:

16:

64:


If this color-interpolation issue were solved then we could map any image onto a surface.

2 Likes