I know that this topic has already occured a few times in the forum but I still would like to ask if it is possible to use a color image for coloring a surface plot. Specifically, I do not understand why my code is not working . Maybe you could help me out or at least explain me why it does not work .
As mentioned I am trying to use an image to color a surface. At first I am loading the image:
import numpy as np
import matplotlib.pyplot as plt
import plotly.graph_objects as go
im = plt.imread('Peacock.jpg')[::5, ::5] # reduce overall image size
plt.imshow(im)
Next, I make some surface according to some basically random function (in reality I have an image from a 3D microscope with its color image equivalent).
x = np.linspace(0, 5, im.shape[1])
y = np.linspace(5, 10, im.shape[0])
X, Y = np.meshgrid(x,y)
z = (X+Y)/(2+np.cos(X)*np.sin(Y))
fig = go.Figure(data=go.Surface(z=z))
fig.show()
Next, I transfer my image data to numbers between 0 and 1 with just constantly increasing values from one corner to the other:
im_first_channel = im[:, :, 0]
image_data = (np.arange(im_first_channel.size).reshape(im_first_channel.shape)/im_first_channel.size).round(5)
image_data
So the image looks like this:
array([[0.0000e+00, 1.0000e-05, 2.0000e-05, ..., 2.4600e-03, 2.4700e-03,
2.4800e-03],
[2.4900e-03, 2.5000e-03, 2.5100e-03, ..., 4.9500e-03, 4.9600e-03,
4.9700e-03],
[4.9800e-03, 4.9800e-03, 4.9900e-03, ..., 7.4300e-03, 7.4400e-03,
7.4500e-03],
...,
[9.9254e-01, 9.9255e-01, 9.9256e-01, ..., 9.9500e-01, 9.9501e-01,
9.9502e-01],
[9.9502e-01, 9.9503e-01, 9.9504e-01, ..., 9.9748e-01, 9.9749e-01,
9.9750e-01],
[9.9751e-01, 9.9752e-01, 9.9753e-01, ..., 9.9997e-01, 9.9998e-01,
1.0]])
Then I am making a color scale with always twice the same color where the colors are the color of each of the pixels in an ascending manner:
color_scale1 = [[val, f"rgb({r},{g},{b})"] for val, (r, g, b) in zip(image_data.flatten(), im.reshape((image_data.size, -1)))]
color_scale2 = [[round(val+1/z.size, 6), f"rgb({r},{g},{b})"] for val, (r, g, b) in zip(image_data.flatten(), im.reshape((image_data.size, -1)))]
color_scale = []
for val1, val2 in zip(color_scale1, color_scale2):
color_scale.extend([val1, val2])
color_scale[-10:]
And then the color scale looks like this:
[[0.99995, 'rgb(51,51,25)'],
[0.999959, 'rgb(51,51,25)'],
[0.99996, 'rgb(32,33,0)'],
[0.999969, 'rgb(32,33,0)'],
[0.99997, 'rgb(44,52,13)'],
[0.999979, 'rgb(44,52,13)'],
[0.99998, 'rgb(49,60,20)'],
[0.999989, 'rgb(49,60,20)'],
[0.99999, 'rgb(31,33,12)'],
[1.0, 'rgb(31,33,12)']]
So, from my understanding I now have a color scale with the colors of each pixel that is normalized between 0 and 1. With the new image that also has the pixels between 0 and 1 ascending the corresponding colors should be used for the surface, thus showing the image. (I am adding half of the difference between to values to the data so that I am in between the two constant color values). However, the output looks like this when I run the following code:
fig = go.Figure(data=go.Surface(z=z,
colorscale=color_scale,
surfacecolor=colors_values+1/z.size/2,
showscale=False))
fig.show()
I honestly do not understand why my approach is not working . At least, what you can see is that in the final image The color changes from one corner to the other but plotly
does not seem to be using my color scale. Can someone tell me why it is not working?
Thanks in advance for your answers .