Create CPython components using Hops in Grasshopper

Worked , thanks :slight_smile:

By the way, it would be easier for me to read your posts if you pasted python code into your posts instead of screenshots of code. Sometimes the resolution of the image makes things hard to read on my computer.
Thanks

Thank you , i will do that :slight_smile:

http server work better even i close the file and open it again hops component work

So this problem is solved

Update
The problem still exist but it can be solved like this (using http server):
If the url in the saved file is http://127.0.0.1:5000/....... it must be replaced with http://localhost:5000/...... and vise versa

2 Likes

Hi @stevebaer,

Is there any way to use custom objects as inputs/outputs in Hops-server?
That is, using something other than HopsString / HopsInteger / etc. for input and output of the components?

Thanks!

1 Like

Not right now, but we can investigate ways to support this. My first inclination is to use something like jSwan to convert your data into json and pass that json as a string input to CPython

Thanks for the great work! The entire Hops thing is a great way to work more dynamically with grasshopper definitions.
I have not fully gone into the python definition on github, but I am at the moment not able to use Lists as input. In the python classes however ITEM, LIST and TREE exist, but am I correct that this is not operational yet?
And alsoā€¦ what is the syntax to have multiple outputs (as item, list, tree)?

That is correct. Iā€™m hoping to ship a new version of ghhops-server library very soon with list support.

3 Likes

ghhops-server 1.2.0 now on available on pypi

You should be able to have lists as inputs and outputs now. Hereā€™s a modified version of the pointat sample that

  • takes a curve and a list of numbers as input
  • returns a list of points
@hops.component(
    "/pointsat",
    name="PointsAt",
    nickname="PtsAt",
    description="Get points along curve",
    icon="examples/pointat.png",
    inputs=[
        hs.HopsCurve("Curve", "C", "Curve to evaluate"),
        hs.HopsNumber("t", "t", "Parameters on Curve to evaluate", hs.HopsParamAccess.LIST),
    ],
    outputs=[
        hs.HopsPoint("P", "P", "Points on curve at t")
    ]
)
def pointsat(curve, t):
    points = [curve.PointAt(item) for item in t]
    return points
5 Likes

@stevebaer, it appears to be working correctly without having to state the HopsParamAccess:

https://hops-online.herokuapp.com/plevels

ITEM and LIST access are only really used for defining inputs. By default, the input is defined as Item and you python function will get a single item for the input parameter. When set to LIST, the input parameter will be a list.

True; I was forgetting about that.

Also works pretty well for interop with other programs :wink:
Hereā€™s BlenderHops:

24 Likes

Thatā€™s awesome, @tom_svilans!

Does it connect automatically to a running session in Blender and extract all meshes?

You boot the script in Blender and attach to the Flask app as in the example script, but running it from Blender gives you access to bpy and all the Blender data. Itā€™s not more than that, and it freezes the Blender UI because the Flask app ties up the script execution, which could probably be developed into something that runs in the background somehow.

But, as an example of using Hops it with whatever Python environment you have available, it does seem to be very powerfulā€¦

4 Likes

Here is a webinar to learn how to use Hops, CPython and Machine learning together. This would apply to any external libraries, applications or services that have a Python API.

8 Likes

Lealand Curtis does a great job here explaining the necessity of Grasshopper, Cpython and Hops in more advanced Machine Learning tools. And he gets into some of the code he used to connect them all together:

11 Likes

Hi,
Iā€™m getting a weird error in the Hops component in Grasshopper. Iā€™ve defined a function in Python that returns a mesh, exactly as my previous Blender example.
However, now it refuses to connect with Grasshopper, and gives this error:
1. Solution exception:Unexpected character encountered while parsing value: U. Path '', line 0, position 0.

The path is http://localhost:5000/getmesh and Iā€™ve also tried with http://127.0.0.1:5000/getmesh.

Any ideas about what might be causing it to fail? Also, is there a manual way to clear the caches? It often gives me an error message about code that has been changed (when it worked before), making me think that there was still a Flask app or something working in the backgroundā€¦

Face Emotion Recognizer test

from flask import Flask
import ghhops_server as hs
from fer import FER
import cv2
import rhino3dm

# register hops app as middleware
app = Flask(__name__)
hops = hs.Hops(app)

@hops.component(
    "/emotion",
    name="emotion",
    description="detect face emotion",
    icon="",
    inputs=[
        hs.HopsString("Image", "I", "Image file"),
        hs.HopsNumber("Index", "i", "Face index")
    ],
    outputs=[
        hs.HopsCurve("Curve", "C", "rectangle"),
        hs.HopsString("Top Emotion", "T", "Top Emotion"),
        hs.HopsString("Emotions", "E", "Emotions result")
    ]
)
def emotion(image,index):
    img = cv2.imread(image)
    detector = FER(mtcnn=True)
    result = detector.detect_emotions(img)
    top = []
    for i in range(len(result)):
        top_emotions = [max(e["emotions"], key=lambda key: e["emotions"][key]) for e in result]
        top_emotion = top_emotions[i]
        score = result[i]["emotions"][top_emotion]
        top.append([top_emotion, score])
    print(top)
    emotions_list = []
    rectangles = []
    for idx, name in enumerate(result):
        emotions = name["emotions"]
        bbox = name["box"]
        p1 = rhino3dm.Point3d(bbox[0], -bbox[1], 0)
        p2 = rhino3dm.Point3d(bbox[0], -bbox[1] - bbox[3], 0)
        p3 = rhino3dm.Point3d(bbox[0] + bbox[2], -bbox[1] - bbox[3], 0)
        p4 = rhino3dm.Point3d(bbox[0] + bbox[2], -bbox[1], 0)
        pts = [p1, p2, p3, p4, p1]
        poly = rhino3dm.Polyline(pts).ToPolylineCurve()
        rectangles.append(poly)
        emotions_list.append(emotions)

    print (rectangles)
    return rectangles[int(index)], top[int(index)], emotions_list

if __name__ == "__main__":
    app.run()
16 Likes

Haha, great example! :slight_smile:

2 Likes

Oh, you managed to create multiple outputs out of the Hops with CPython! I had a problems with that for some reason :slight_smile:

Cool example!

2 Likes