Chocolate Beans in Glass¶
In this subsequent tutorial, once again, we will focus on our tasty chocolate beans. We will introduce a further object – a glass with transmissive, refractive material – to the scene, which influences the view on the particles. The perspective of our camera will be subject to variation. Our main focus lies on the difference between the particles’ behavior and appearance on the final images when comparing the scene with and without glass.
At a Glance¶






What We Will Learn¶
Closer look at
RelaxCollisions
function, incl.dry_run
Enable/disable scene objects
Slim down recipe with inheritance
Use multirun to output image series
Randomize scene by various parameters
Step 1: Tidy Up!¶
We start this tutorial by using the inheritance
mechanism a little bit different than before: Our recipe from the previous tutorial grew to a proud size of 303 code lines, all together.
# Initializing and seeding
defaults: …
initial_runtime_state: …
# Defining blueprints
blueprints:
measurement_techniques: …
particles: …
# Physical boundary conditions
process_conditions:
feature_criteria:
IsCat1: …
⋮
IsCat8: …
IsPink: …
sets:
Category1: …
⋮
Category8: …
PinkParticles: …
feature_variabilities:
CameraNearTable: …
InitialParticleLocation: …
ParticleDimension: …
ParticleWidth: …
ParticleHeight: …
PinkColor: …
RedColor: …
OrangeColor: …
YellowColor: …
GreenColor: …
BlueColor: …
PurpleColor: …
BrownColor: …
RenderingResolutionPercentage: …
CyclesSamples: …
# Procedural steps of synthetization chain
synth_chain:
feature_generation_steps:
- _target_: $builtins.InvokeBlueprints # MeasurementTechnique …
- _target_: $builtins.InvokeBlueprints # Particles …
- _target_: $builtins.TriggerFeatureUpdate # cam_location_z …
- _target_: $builtins.TriggerFeatureUpdate # location …
- _target_: $builtins.TriggerFeatureUpdate # dimensions …
- _target_: $builtins.TriggerFeatureUpdate # width …
- _target_: $builtins.TriggerFeatureUpdate # height …
- _target_: $builtins.TriggerFeatureUpdate # color(pink) …
- _target_: $builtins.TriggerFeatureUpdate # color(red) …
- _target_: $builtins.TriggerFeatureUpdate # color(orange) …
- _target_: $builtins.TriggerFeatureUpdate # color(yellow) …
- _target_: $builtins.TriggerFeatureUpdate # color(green) …
- _target_: $builtins.TriggerFeatureUpdate # color(blue) …
- _target_: $builtins.TriggerFeatureUpdate # color(purple) …
- _target_: $builtins.TriggerFeatureUpdate # color(brown) …
- _target_: $builtins.RelaxCollisions # avoid intersections …
- _target_: $builtins.RelaxCollisions # gravity …
- _target_: $builtins.TriggerFeatureUpdate # resolution …
- _target_: $builtins.TriggerFeatureUpdate # render samples …
rendering_steps:
- _target_: $builtins.SaveState …
- _target_: $builtins.RenderParticlesTogether # real …
- _target_: $builtins.RenderParticlesTogether # cat(all) …
- _target_: $builtins.RenderParticlesTogether # cat(pink) …
- _target_: $builtins.RenderParticlesIndividually # pink …
Now – to make navigating and handling the recipe easier and less prone to errors – we want to sort the parts a little bit and shrink down the main recipe to those elements, which are essential and those elements, which we often want to touch.
First, we will create three new files:
chocBeans_glassTable.yaml
, our main recipes_SceneVariation.yaml
, scene description, incl. blueprintss_BeanParams.yaml
, the parameters of ourBeads
s_ColorCategories.yaml
, sets and color definitions
As a first step, in our main recipe, we add our usual Initializing and seeding
block. Under defaults:
, we will now include those three further files (we used the prefix s_
here to mark the files as “supplementary” = not a stand-alone recipe; this naming convention is arbitrary).
# Initializing and seeding
defaults:
- BaseRecipe
- s_SceneVariation
- s_BeanParams
- s_ColorCategories
- _self_
initial_runtime_state:
seed: 42
As mentioned above, we want to keep the parts in the main recipe, which we touch more often and outsource the parts, we rarely or never touch after definition. So, we continue in our main recipe and copy over the two feature_variabilities
for the features resolution_percentage
and cycles_samples
.
# Initializing and seeding
defaults: …
initial_runtime_state: …
# Physical boundary conditions
process_conditions:
feature_variabilities:
RenderingResolutionPercentage:
feature_name: resolution_percentage
variability:
_target_: $builtins.Constant
value: 25
CyclesSamples:
feature_name: cycles_samples
variability:
_target_: $builtins.Constant
value: 64
We will not need any other process_conditions
in our main recipe. However unfortunately, the synth_chain
we need to copy over as a whole, since we want to make some changes here. As mentioned earlier, in the current version of synthPIC2
, it is not allowed to change/add only single elements of the both lists feature_generation_steps
and rendering_steps
by inheritance, but only to replace them as a whole. In the latter case – in the sequence defined at the very top under defaults:
– every newly introduced list of feature_generation_steps
or rendering_steps
from a subsequent recipe will completely replace its predecessor.
# Procedural steps of synthetization chain
synth_chain:
feature_generation_steps:
- _target_: $builtins.InvokeBlueprints
affected_set_name: AllMeasurementTechniqueBlueprints
- _target_: $builtins.InvokeBlueprints
affected_set_name: AllParticleBlueprints
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: CameraNearTable
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: InitialParticleLocation
affected_set_name: AllParticles
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: ParticleDimension
affected_set_name: AllParticles
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: ParticleWidth
affected_set_name: AllParticles
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: ParticleHeight
affected_set_name: AllParticles
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: PinkColor
affected_set_name: Category1
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: RedColor
affected_set_name: Category2
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: OrangeColor
affected_set_name: Category3
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: YellowColor
affected_set_name: Category4
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: GreenColor
affected_set_name: Category5
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: BlueColor
affected_set_name: Category6
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: PurpleColor
affected_set_name: Category7
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: BrownColor
affected_set_name: Category8
- _target_: $builtins.RelaxCollisions
affected_set_name: AllParticles
num_frames: 5
time_scale: 10
collision_shape: CONVEX_HULL
- _target_: $builtins.RelaxCollisions
affected_set_name: AllParticles
use_gravity: True
damping: 0.07
friction: 0.999
restitution: 0.001
collision_margin: 0.001
num_frames: 200
collision_shape: CONVEX_HULL
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: RenderingResolutionPercentage
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: CyclesSamples
affected_set_name: AllMeasurementTechniques
rendering_steps:
- _target_: $builtins.SaveState
name: state
- _target_: $builtins.RenderParticlesTogether
rendering_mode: real
do_save_features: True
- _target_: $builtins.RenderParticlesTogether
rendering_mode: categorical
output_file_name_prefix: all_
- _target_: $builtins.RenderParticlesTogether
rendering_mode: categorical
set_name_of_interest: PinkParticles
output_file_name_prefix: pink_
- _target_: $builtins.RenderParticlesIndividually
rendering_mode: categorical
set_name_of_interest: PinkParticles
subfolder: pink
With the main recipe file chocBeans_glassTable.yaml
we’re done. Let’s now outsource the rest of our previous recipe file chocBeans_table.yaml
. In the newly created, supplementary file s_SceneVariation.yaml
, we add all information about the blueprints
, the general scene layout as well as the perspective view.
# Defining blueprints
blueprints:
measurement_techniques:
TopCamInAir:
measurement_technique_prototype_name: woodTable_sideCam
measurement_volume_material_prototype_name: vacuum
background_material_prototype_name: wood
particles:
Bead:
geometry_prototype_name: ellipsoid
material_prototype_name: colored_subtle
parent: MeasurementVolume
number: 200
# Physical boundary conditions
process_conditions:
feature_variabilities:
CameraNearTable:
feature_name: cam_location_z
variability:
_target_: $builtins.Constant
value: -35.0
The second newly created supplementary file s_BeanParams.yaml
will hold all information, i.e. features
we want to manipulate, about our particles.
# Physical boundary conditions
process_conditions:
feature_variabilities:
InitialParticleLocation:
feature_name: location
variability:
_target_: $builtins.UniformlyRandomLocationInMeasurementVolume
ParticleDimension:
feature_name: dimensions
variability:
_target_: $builtins.UniformDistribution3dHomogeneous
location: 3.58
scale: 0.6
ParticleWidth:
feature_name: width
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: 0.85
scale: 0.15
num_dimensions: 1
ParticleHeight:
feature_name: height
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: 0.475
scale: 0.15
num_dimensions: 1
The last of the three supplementary files s_ColorCategories.yaml
defines all the feature_criteria
, the sets
and the feature_variabilities
, which are related to color definition.
# Physical boundary conditions
process_conditions:
feature_criteria:
IsCat1:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 1
compartments_total: 8
default_return_value: False
IsCat2:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 2
compartments_total: 8
default_return_value: False
IsCat3:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 3
compartments_total: 8
default_return_value: False
IsCat4:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 4
compartments_total: 8
default_return_value: False
IsCat5:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 5
compartments_total: 8
default_return_value: False
IsCat6:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 6
compartments_total: 8
default_return_value: False
IsCat7:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 7
compartments_total: 8
default_return_value: False
IsCat8:
_target_: $plugins.official.InCompartment
feature_name: location_z
compartment_no: 8
compartments_total: 8
default_return_value: False
IsPink:
_target_: $plugins.official.InHsvRange
feature_name: color
h_min: 0.945
h_max: 0.950
s_min: 0.895
s_max: 0.900
v_min: 0.648
v_max: 0.653
default_return_value: False
sets:
Category1:
criterion: $IsParticle and $IsCat1
Category2:
criterion: $IsParticle and $IsCat2
Category3:
criterion: $IsParticle and $IsCat3
Category4:
criterion: $IsParticle and $IsCat4
Category5:
criterion: $IsParticle and $IsCat5
Category6:
criterion: $IsParticle and $IsCat6
Category7:
criterion: $IsParticle and $IsCat7
Category8:
criterion: $IsParticle and $IsCat8
PinkParticles:
criterion: $IsParticle and $IsPink
feature_variabilities:
PinkColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.945
h_max: 0.950
s_min: 0.895
s_max: 0.900
v_min: 0.648
v_max: 0.653
RedColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.990
h_max: 0.995
s_min: 0.995
s_max: 1.000
v_min: 0.448
v_max: 0.453
OrangeColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.020
h_max: 0.025
s_min: 0.995
s_max: 1.000
v_min: 0.895
v_max: 0.900
YellowColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.087
h_max: 0.092
s_min: 0.945
s_max: 0.950
v_min: 0.862
v_max: 0.867
GreenColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.321
h_max: 0.326
s_min: 0.770
s_max: 0.775
v_min: 0.253
v_max: 0.258
BlueColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.622
h_max: 0.627
s_min: 0.846
s_max: 0.851
v_min: 0.547
v_max: 0.552
PurpleColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.716
h_max: 0.721
s_min: 0.801
s_max: 0.806
v_min: 0.348
v_max: 0.353
BrownColor:
feature_name: color
variability:
_target_: $plugins.official.RandomHsvColorAsRgb
h_min: 0.020
h_max: 0.025
s_min: 0.796
s_max: 0.801
v_min: 0.082
v_max: 0.087
When we render our newly created main recipe, which contains basically “only” a better sorted version of our recent recipe chocBeans_table
, we will find – surprise, surprise – exactly the same output in the folder output/chocBeans_glassTable/<YYYY-MM-DD_hh-mm-ss>/run0/
and its subfolders, as we produced in the end of the previous tutorial.
python run.py --config-dir=recipes --config-name=chocBeans_glassTable






Okay, easy start. Wasn’t it? Just some copy-pasting. In the next step, we will have a look at our main goal in this tutorial. But before we go there, here’s a little overview of the recipe files, which we just created. Take this little summary of the long code blocks’ content from before to recap this first step and to appreciate the possibility to use inheritance for recipes.
# Initializing and seeding
defaults:
- BaseRecipe
- s_SceneVariation
- s_BeanParams
- s_ColorCategories
- _self_
initial_runtime_state: …
# Physical boundary conditions
process_conditions:
feature_variabilities:
RenderingResolutionPercentage: …
CyclesSamples: …
# Procedural steps of synthetization chain
synth_chain:
feature_generation_steps: …
rendering_steps: …
# Defining blueprints
blueprints:
measurement_techniques: …
particles: …
# Physical boundary conditions
process_conditions:
feature_variabilities:
CameraNearTable: …
# Physical boundary conditions
process_conditions:
feature_variabilities:
InitialParticleLocation: …
ParticleDimension: …
ParticleWidth: …
ParticleHeight: …
# Physical boundary conditions
process_conditions:
feature_criteria:
IsCat1: …
⋮
IsCat8: …
IsPink: …
sets:
Category1: …
⋮
Category8: …
PinkParticles: …
feature_variabilities:
PinkColor: …
⋮
BrownColor: …
Step 2: What to Achieve and How to Approach¶
As promised, let’s try to envision where we’re going here: We first just took the recipe from the previous tutorial. We sorted it into several helper/supplementary files for the sake of being able to keep the overview and to still be able to handle it.
Next, we want to introduce a further object, namely a glass. We place this below our chocolate beans to catch those falling particles during the physics simulation.
Then we will have two cases for our synthesized particles: The first without, the second with the glass, which was introduced to the scene.
We will compare these two and focus on some questions.
“How will the particles’ movement differ between the cases with and without glass, starting with exactly the same location of each particle?”
“How do the particles behave, assuming different physics?”, i.e. different parameters of the
RelaxCollisions
function.“How will the particles’ appearance differ with and without glass?”
“What’s the influence of the gravity?”, i.e. changing the gravity vector
“How many chocolate beans are good for us?”
We do this rather detailed investigation of how exactly the particles fall, since this is our last fine-tuning step, before we go into “series production”, i.e. batch processing to output multiple randomized images – all of course from chocolate beans and with every feature
restricted only to the allowed ranges, which were specified by us.
To actually do something in this step, let’s at least prepare the scene for the experiments with parameter variation, which we will perform in the next step. We will first “activate” the glass. To our supplementary file s_SceneVariation.yaml
, we will add two more feature_variabilities
.
# Defining blueprints
blueprints:
measurement_techniques: …
particles: …
# Physical boundary conditions
process_conditions:
feature_variabilities:
CameraNearTable: …
ShowGlass:
feature_name: glass_hide
variability:
_target_: $builtins.Constant
value: False
CollisionGlass:
feature_name: glass_collision
variability:
_target_: $builtins.Constant
value: True
In our main recipe chocBeans_glassTable.yaml
, we add the corresponding feature_generation_steps
, because our main recipe holds the complete list of feature_generation_steps
. Let’s add the two TriggerFeatureUpdates
directly after our two InvokeBlueprints
steps.
synth_chain:
feature_generation_steps:
- _target_: $builtins.InvokeBlueprints …
- _target_: $builtins.InvokeBlueprints …
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: ShowGlass
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: CollisionGlass
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate …
Executing the recipe will output the rendered image showing our chocolate beans captured by the glass.

Okay, the glass is there, but the view isn’t nice. To change this, let’s just remove (or comment out) the corresponding TriggerFeatureUpdate
step from our list of feature_generation_steps
.
synth_chain:
feature_generation_steps:
- _target_: $builtins.InvokeBlueprints …
- _target_: $builtins.InvokeBlueprints …
- _target_: $builtins.TriggerFeatureUpdate …
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: CollisionGlass
affected_set_name: AllMeasurementTechniques
# - _target_: $builtins.TriggerFeatureUpdate
# feature_variability_name: CameraNearTable
# affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: InitialParticleLocation
affected_set_name: AllParticles
If you like, you could also remove the feature variability
from our process_conditions
in the file s_SceneVariation.yaml
. However, you could also just leave it there. Doesn’t matter, it’s personal preference depending on how keen you are with tidying up (or if you purposefully want to leave those code snippets for later playing around & fast access to change those features once again).
We will change two more things. First, let’s turn on the dry_run
for our second RelaxCollisions
function again: We want to see how the particles are falling in the next step!
- _target_: $builtins.RelaxCollisions …
- _target_: $builtins.RelaxCollisions
affected_set_name: AllParticles
use_gravity: True
damping: 0.07
friction: 0.999
restitution: 0.001
collision_margin: 0.001
num_frames: 200
collision_shape: CONVEX_HULL
dry_run: True
Second, we comment out the categorical rendering steps for the moment. We are not interested in those at the moment. But don’t worry, we’ll turn it on again, later in step 4.
rendering_steps:
- _target_: $builtins.SaveState …
- _target_: $builtins.RenderParticlesTogether
rendering_mode: real
do_save_features: True
# - _target_: $builtins.RenderParticlesTogether
# rendering_mode: categorical
# output_file_name_prefix: all_
# - _target_: $builtins.RenderParticlesTogether
# rendering_mode: categorical
# set_name_of_interest: PinkParticles
# output_file_name_prefix: pink_
# - _target_: $builtins.RenderParticlesIndividually
# rendering_mode: categorical
# set_name_of_interest: PinkParticles
# subfolder: pink
If we would turn off the particles for a second (just for this one render: comment out the InvokeBlueprints
of our particles and the TriggerFeatureUpdates
for color), we’d see our glass on the table – with well positioned camera view. Everything is prepared now for the next step with experiments to investigate parameter variation.

Step 3: Playing God and Change the Physics¶
If you commented them out to see only the glass in the last step, comment them in again, the lines for InvokeBlueprints
of our particles and the TriggerFeatureUpdates
for color.
Now, you are free to change and play around with some parameters. You could try the following variations (see also subsequent images):
Simulate with and without glass (try different combinations of
ShowGlass
and/orCollisionGlass
).Use our previous parameters of
RelaxCollisions
, try changing parameters ofRelaxCollisions
, e.g. play around withdamping
,friction
andrestitution
. Try new parametersmass
,gravity
. (Hints: leavedry_run
turned on and keepSaveState
inrendering_steps
to observe the effect. A smaller value fornum_frames
is advised. When doing large parameter variation experiments, multirun should be used, see next step.)Let the particles fall sideways… everything possible! Therefore, you would need to change the
gravity
vector – keep in mind: this should be input as a list.You could try more particles & longer (
num_frames
) simulation time.




The example images show the behavior of our chocolate beans, when a glass is present and when there is no glass and the particles can freely distribute on the table. Furthermore, the third image shows how the particle appearance would look like if there would be a physical (CollisionGlass
), but not a visual (ShowGlass
) influence of the glass. This case is quite interesting: It demonstrates, how our particles would look like – placed in the same position, but if glass would be invisible. Meaning, if there wouldn’t be the refraction of the glass, which distorts the particles’ appearances and eventually moves/changes the information of each particle (i.e. colored pixels) to different pixel locations in the final image. If your use case would be, e.g. to measure the 2D projected area of those chocolate beans with a certain color in the final image, the influence of how strong the glass distorts this truth could be quantified. The last image shows the result if our particles would fall sideways, with a different gravity
vector applied, see code snippet below.
- _target_: $builtins.RelaxCollisions …
- _target_: $builtins.RelaxCollisions
affected_set_name: AllParticles
use_gravity: True
damping: 0.07
friction: 0.999
restitution: 0.001
collision_margin: 0.001
gravity:
- +5
- -5
- 0
num_frames: 200
collision_shape: CONVEX_HULL
dry_run: True
After some variation of our chocolate beans’ quantity, a number of 500 particles looks quite appropriate, resulting in a completely filled glass and a few particles falling on the wooden table – not too many, just the right amount. Also after tinkering around with the parameters of RelaxCollisions
, we seem to have found our final parametrization, see video below (extended to num_frames: 600
as opposed to num_frames: 200
for our final renders) and subsequent code snippets.
# Defining blueprints
blueprints:
measurement_techniques: …
particles:
Bead:
geometry_prototype_name: ellipsoid
material_prototype_name: colored_subtle
parent: MeasurementVolume
number: 500
- _target_: $builtins.RelaxCollisions
affected_set_name: AllParticles
mass: 0.0012
num_frames: 5
time_scale: 10
collision_margin: 0.001
collision_shape: CONVEX_HULL
- _target_: $builtins.RelaxCollisions
affected_set_name: AllParticles
use_gravity: True
damping: 0.07
friction: 0.4
restitution: 0.1
mass: 0.0012
collision_margin: 0.001
num_frames: 200
collision_shape: CONVEX_HULL
dry_run: True
Step 4: Variation in Series Production¶
In this last step of our tutorial, we want to go for the fully automated particle generation under (pseudo-)random parameter variation of the scene. We do so, by just simply varying the initial_runtime_state.seed
.
But first let’s comment in the categorical render_steps
again.
rendering_steps:
- _target_: $builtins.SaveState …
- _target_: $builtins.RenderParticlesTogether
rendering_mode: real
do_save_features: True
- _target_: $builtins.RenderParticlesTogether
rendering_mode: categorical
output_file_name_prefix: all_
- _target_: $builtins.RenderParticlesTogether
rendering_mode: categorical
set_name_of_interest: PinkParticles
output_file_name_prefix: pink_
- _target_: $builtins.RenderParticlesIndividually
rendering_mode: categorical
set_name_of_interest: PinkParticles
subfolder: pink
Furthermore, we will add several new feature_variabilities
to our s_SceneVariation.yaml
file.
# Defining blueprints
blueprints:
measurement_techniques: …
particles: …
# Physical boundary conditions
process_conditions:
feature_variabilities:
CameraNearTable: …
ShowGlass: …
CollisionGlass: …
CameraRotation:
feature_name: cam_rotation
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: -0.0523598775598299
scale: 0.10471975511966
num_dimensions: 1
CameraAltitude:
feature_name: cam_altitude
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: -0.15707963267949
scale: 0.314159265358979
num_dimensions: 1
CameraAzimuth:
feature_name: cam_azimuth
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: 0.0
scale: 6.28318530717959
num_dimensions: 1
GlassRotation:
feature_name: glass_rotation
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: 0.0
scale: 0.698131700797732
num_dimensions: 1
TableRotation:
feature_name: table_rotation
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: 0.0
scale: 6.28318530717959
num_dimensions: 1
WoodTexture:
feature_name: texture_seed
variability:
_target_: $builtins.UniformDistributionNdHomogeneous
location: 0
scale: 1000
num_dimensions: 1
…and we need to trigger those in our main recipe file chocBeans_glassTable.yaml
synth_chain:
feature_generation_steps:
- _target_: $builtins.InvokeBlueprints …
⋮
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: BrownColor
affected_set_name: Category8
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: CameraRotation
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: CameraAltitude
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: CameraAzimuth
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: GlassRotation
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: TableRotation
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.TriggerFeatureUpdate
feature_variability_name: WoodTexture
affected_set_name: AllMeasurementTechniques
- _target_: $builtins.RelaxCollisions …
⋮
These new feature variations will introduce random variations of the camera angle and the rotations of the glass, table and wood texture of the table. As a final measure we increase the RenderingResolutionPercentage
and the CyclesSamples
to get a high-resolution image as output.
To call the execution we now execute our recipe as we normally do with the addition of the argument multirun
python run.py --config-dir=recipes --config-name=chocBeans_glassTable --multirun initial_runtime_state.seed="range(10)"
The number in brackets behind range
can be set to the desired number of output images. The images below show some example images of our fully automated series production of chocolate beans, whereas all captures are unique and randomized in various parameters.

















