This tutorial will take you through adding your first modifier node to the example channel. Modifiers nodes can manipulate 3D objects or other scene components and parameters to introduce variation. Variation is essential for creating large datasets with diverse imagery. Specifically, we’ll be adding a modifier node that will adjust the scale of the objects in the scene.

Scaling Objects in Blender

The example channel uses Blender to build scenes. All objects are loaded into Blender and can be manipulated using Blender python calls. First we’ll look at Blender to learn what we need to implement to adjust the scale of an object.

Opening Blender

For this tutorial, we’ll download Blender from https://www.blender.org/download/. For this tutorial we use Blender 2.90, the same version of Blender that is in the Example channel environment. It is important to note that Blender python calls can change between versions of Blender. When we first open Blender, we are greeted with a screen similar to the one below:

In this starting scene we have a camera, a light and The next thing we’ll want to do is learn how to manipulate the scale of the Cube object.

Manipulating the Scale

We can set scale of the Cube object by first selecting the object in the 3D Viewport then setting the Scale properties for the X,Y,Z dimensions under the Object Properties tab. In the example below we set the scale to 5 for each of the dimensions, [5,5,5].

Finding the Python SDK call

In this example, we want to be able to allow a channel user to configure object scale without having to use Blender. The way to do this is to create a node that will include Blender python calls that modify an object. To figure out the python call to make that will scale an object, we use the Scripting view at the top of the 3D Viewport in Blender. This will provide us with a list of python calls made in the Blender session. The three most recent calls should be the calls we made to scale the Cube object.

Blender will use the the current context to determine which object to scale, indicated with the bpy.context.object prefix. In the example channel, we use the AnaObject class to reference the Blender object. An example of how we would set the scale for an AnaObject is shown below:

obj.root.scale = [5,5,5]
PY

Adding the Modifier Code

To add the Scale Modifier to the example channel we will need to add a few files to the example package. The first two files we will add will be the Scale Modifier Node definition and the second will be the Scale Modifier Node schema. These will define the input and outputs of the node and what command will be called when the modifier is used. We create scale_modifier.py and scale_modifier.yml under the example/packages/example/example/nodes directory.

scale_modifier.py

from anatools.lib.node import Node
from anatools.lib.generator import ObjectModifier

class ScaleModifier(Node):
    """
    A class to represent the ScaleModifier node, a node that can modify the scale of an object.
    """
    def exec(self):
        generator = ObjectModifier(
            method="scale",
            children=self.inputs["Generators"],
            scale=self.inputs["Scale"][0])
        return {"Generators": generator}
CODE

scale_modifier.yml

schemas:
  ScaleModifier:
    alias: Scale
    inputs:
    - name: Scale
      description: The scale value to set the objects to.
      default: 1
    - name: Generators
      description: Object Generators to set the scale for.
    outputs:
    - name: Generator
      description: The modified Object Generators
    tooltip: Changes the scale of objects.
    category: Modifiers
    subcategory: Scale
    color: "#B32424"
CODE

The next file we’ll update is the existing object_generators.py, where we will update the Example Channel Object class to add a scale method. In this method is where we will call the Blender object’s scale property, we will be scaling the objects to the same value in all three dimensions.

object_generators.py

class ExampleChannelObject(AnaObject):
    """
    A class to represent the Example Channel AnaObjects.
    Add a 'color' method for the objects of interest.
    """

    def color(self, color_type=None):
        pass

    def scale(self, scale):
        self.root.scale = [scale,scale,scale]
CODE


Now that our Scale Modifier node has been implemented, we’ll want to test out our code to ensure it runs as planned and we are getting the results we want.

Testing Locally

The first thing we’ll do is modify the default graph for the channel to include the scale modifier. In example/graphs/default.yml, we will add Scale Modifier to modify the scale of the Rubik’s Cube. We will also replace the Object Placement node’s input for the Rubik’s Cube output with the output from the Scale Modifier.

default.yml

  ScaleModifier:
    nodeClass: Scale
    values: {Scale: 2}
    links:
      Generators:
        - {sourceNode: "Rubik's Cube", outputPort: "Rubik's Cube Generator"}
        
  ObjectPlacement:
    nodeClass: Random Placement
    values: {Number of Objects: 20}
    links:
      Object Generators:
      - {sourceNode: ColorToys, outputPort: Generator}
      - {sourceNode: ScaleModifier , outputPort: Generator}
      - {sourceNode: Mix Cube, outputPort: Mixed Cube Generator}
CODE


After making these changes, it's time to run Ana again to see what has changed. Note that the example is set to create Rubik’s cubes that are twice as big as the original, all other objects will remain the same size.

Let's test again, but this time setting the Scale parameter to 0.5.

If we are happy with the results, its ready to deploy to the platform so we can use the Scale Modifier when creating new datasets.

To deploy a channel, reference the Channel Deployment documentation atDeploying a Channel. We will be deploying over the custom_channel in our default Organization in this tutorial.

Using our new Node in a Graph

After the channel has successfully deployed, we can use our Modifier in our custom_channel graphs. In the Nodes section on the left, we should be able to find our Scale Modifier under the Modifiers > Scale category. We will add this node to our graph.

Next we will configure the inputs and outputs of this node, in this case we will connect the Rubik’s Cube to the Generators input and connect the Generators output to the Drop Object node’s

After we are happy with the graph we can create our new dataset with scaled objects. Below are some examples of the images from a dataset created with a graph that scaled Skateboards randomly from 1-3.

Congratulations, you have created your first modifier node for the example channel!