Python 3 Skelitonization - plt.show() not work

Hi, congratulations on running your sample :slight_smile:
I’m testing skimage package and I can’t see any window with the results. Should plt.show() run the image window? I can save the processed image to file, but cannot see the window with the result. Any advice? Many thanks in advance :wink:

1 Like

Could you try an Image Watch Node?

1 Like

Thanks for getting back to me. Do you mean I could preview what I’ve saved? I can do it - many thanks! But it would be a bit nicer to make plt.show() work. I also tried plt.imgshow() and it’s not working.

1 Like

This is more around a particular python library than Python 3 support, so I am moving it to a new thread. :slight_smile:

2 Likes

Hello
here is a workaround by converting ndarray image to Bitmap (Net Framework), so you can directly use the image in Dynamo

import sys
import clr
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
sys.path.append(r'C:\Users\sneep\AppData\Local\python-3.8.3-embed-amd64\Lib\site-packages')
import System
clr.AddReference('System.Drawing')
import System.Drawing

from System.Drawing import *
from System.Drawing.Imaging import *

import numpy as np
from scipy import misc
from matplotlib import cm
from matplotlib import colors as mcolors
face = misc.face() #ndarray 3 dimmensions
face2dG = misc.face(gray = True) #ndarray 2 dimmensions


def getRGBfromPalette(npArr, colorMapName):
    """ create a palette color from max value in ndarray """
    color_map = cm.get_cmap(colorMapName)
    a_max = np.amax(npArr)
    palettNp = color_map(np.linspace(0, 1, a_max + 1))
    palettRGB = [(r * 255, g * 255, b * 255) for r,g,b,a in palettNp]
    return palettRGB

def convertToBitmap(npImgArray, colorMapNamefor2D = 'viridis'):
    """ create Bitmap from ndarray image """
    palettRGBfor2D = getRGBfromPalette(npImgArray, colorMapNamefor2D)
    bmpOut = Bitmap(npImgArray.shape[1], npImgArray.shape[0])
    for i in range(npImgArray.shape[1]):
        for j in range(npImgArray.shape[0]):
            if npImgArray.ndim == 3:
                subnpArray = npImgArray[j][i]
                bmpOut.SetPixel(i, j, Color.FromArgb(subnpArray[0], subnpArray[1], subnpArray[2]))
            #    
            elif npImgArray.ndim == 2:
                subnpArray = npImgArray[j][i]
                r, g, b = palettRGBfor2D[subnpArray]
                bmpOut.SetPixel(i, j, Color.FromArgb(r, g, b))
            #    
            else:
                pass
            
    return bmpOut

OUT = convertToBitmap(face), convertToBitmap(face2dG, colorMapNamefor2D = 'gray'), convertToBitmap(face2dG, colorMapNamefor2D = 'inferno')
8 Likes

Finally, I found a better (faster) way with Stream conversion, (Bitmap.SetPixel() is too slow)

waveSinCos

import sys
import clr
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
dirAppLoc = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) 
sys.path.append(dirAppLoc + r'\python-3.8.3-embed-amd64\Lib\site-packages')

clr.AddReference('System.Drawing')
import System.Drawing
from System.Drawing import *
from System.Drawing.Imaging import *
from System.IO import MemoryStream

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import io
import math

def plt2arr(fig):
    """
    need to draw if figure is not drawn yet
    """
    fig.canvas.draw()
    rgba_buf = fig.canvas.buffer_rgba()
    (w,h) = fig.canvas.get_width_height()
    rgba_arr = np.frombuffer(rgba_buf, dtype=np.uint8).reshape((h,w,4))
    return rgba_arr

def convertToBitmap2(npImgArray):
    bitmap_ = None
    # remove alpha
    if npImgArray.ndim == 3 and npImgArray.shape[-1] == 4:
        npImgArray = npImgArray[:, :, :-1]
    # convert to PIL Image
    if npImgArray.ndim == 3:
        image = Image.fromarray(npImgArray, "RGB")
    else:
        image = Image.fromarray(npImgArray, "L")
    # convert to Python ByteArray
    byteIO = io.BytesIO()
    image.save(byteIO, format='BMP')
    byteArr = byteIO.getvalue()
    # convert to Net ByteArray
    netBytes = System.Array[System.Byte](byteArr)
    with MemoryStream(netBytes) as ms:
        bitmap_ = Bitmap(ms)
    return bitmap_

# plot sin and cos wave
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.linspace(-np.pi, np.pi)

ax.set_xlim(-np.pi, np.pi)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.plot(x, np.sin(x), label="sin")
ax.plot(x, np.cos(x ), label="cos")
ax.legend()
ax.set_title("sin(x) and cos(x)")

image_from_plot = plt2arr(fig)
bitmap1 = convertToBitmap2(image_from_plot)

OUT = bitmap1
19 Likes

@c.poupin you are Creative and amazing. Thank you.

2 Likes

Working perfect with plot 3d

6 Likes

Thank you very much for your input. Really useful python code !Amazing!

1 Like