Announcing Dash Bio 1.0.0 🎉 : a one-stop-shop for bioinformatics and drug development visualizations.

Unexpected RGB Facecolors in Mesh3D static image

Hello,

I’m plotting a mesh of only 2 faces where each face has a unique color. I save the figure as a static image (PNG) and then read the image back into python using the cv2.imread method.

The PNG looks great and I see the expected colors with my eyes. But, when I look at the RGB data using imread there are 66 unique RGB triplets in the PNG! I expected to see 3 colors in the PNG - Face 1 color, Face 2 color, and the background color.

The colors of the extra RGB triplets are similar to the Face1 and Face2 colors, so I suspect that the lighting could be causing the extra RGB triplets. I’ve tried to set the lighting to only ambient, but the additional colors remain.

Is there a way to save a static image of a mesh3d figure so that the ONLY colors in the PNG are the facecolor RGB triplets? (and figure background)

Here’s my code to generate the mesh3D static image and read it using cv2

import os
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio
import cv2



print('First plot the Mesh')
x = np.array([ 0.,  0.,  0.,  0., 10., 10., 10., 10.])
y = np.array([10.,  0., 10.,  0.,  0., 10., 10.,  0.])
z = np.array([ 0., 10., 10.,  0., 10.,  0., 10.,  0.])
i = np.array([0, 3])
j = np.array([1, 1])
k = np.array([2, 0])
RGBcolors = np.array([[183, 187, 244],
                      [251, 243,  31]])

mesh = go.Mesh3d(
            x=x,
            y=y,
            z=z,                
            i=i,
            j=j,
            k=k,
            facecolor=RGBcolors,
            flatshading=False,
            name='',
            showscale=False)

mesh.update(lighting=dict(ambient= 1.0,
                            diffuse= 0.,
                            fresnel=  0.,
                            specular= 0.,
                            roughness= 0.),
            lightposition=dict(x=100,
                                y=0.,
                                z=0.));

layout = go.Layout(width=1080,
                   height=720,
                    scene=dict(
                        xaxis=dict(range=[-20,20],visible=False),
                               yaxis=dict(range=[-20,20],visible=False),  
                               zaxis=dict(range=[-20,20],visible=False), 
                               camera=dict(
                                      up=dict(x=0, y=0, z=1),
                                      center=dict(x=0, y=0, z=0),
                                      eye=dict(x=-1., y=0., z=0.)),
                        ), 
                  paper_bgcolor='rgb(255,255,255)',
                  margin=dict(t=175)) 
fig = go.Figure(data=[mesh], layout=layout)
fig.show()

# write the image using orca.
imgfile = os.path.join(os.getcwd(),'Cubeface.png')
pio.write_image(fig, imgfile,'png',scale=1,width=1080,height=720,engine='orca')


print('Then read the image')
print('Loading image {}...'.format(os.path.split(imgfile)[-1]))
npimg = cv2.imread(imgfile)

print('Identifying colors...', end = '')
# cv2 reads the file into BGR, but we want to see the color as RGB
npimg = cv2.cvtColor(npimg, cv2.COLOR_BGR2RGB)

# Get unique RGB colors
uniqueRGB, uniqueRGBcounts = np.unique(npimg.reshape(-1, npimg.shape[2]), axis=0, return_counts=True)
print(' Complete! {} unique RGB triplets'.format(len(uniqueRGB)))

# Draw the unique RGB triplets to see what the extra colors look like.
img = np.zeros((512,512,3), np.uint8)
for i,x in enumerate(uniqueRGB):
    tup = (float(x[2]), float(x[1]), float(x[0]))
    cv2.line(img,(0,0),(500,10*i),tup,5)
cv2.imshow('uniqueRGBcolors', img)
cv2.waitKey(0) 

Help! I have to be able to generate an image that only contains the facecolor RGB triplets!

Here’s an example of the static image of the mesh3d. Looks fine. but has 66 unique triplets.