Walkthrough: Generate a random datapoint

This interactive Python notebook will generate a data request that contains instructions for generating a single visual datapoint, built using randomly selected assets from our asset library.

Tip

This page supports an interactive Python kernel that enables you to edit and run the code samples in your browser. To activate the kernel, click “run code” below. If this is the first time you have loaded this page, it may take up to 5 minutes to activate the kernel and install the necessary packages.

!pip install datagen-tech -q

Step 1: Importing relevant modules

In the first code block, we will import the modules that we need.

Important

If you are copying and pasting this code into your own Python environment, make sure to install the datagen-tech python package first.

import datagen.api as datapoint_api
from datagen.api import catalog, assets
from datagen.api.catalog import attributes
from datagen.api.catalog.attributes import Gender, Ethnicity, Age
from pprint import pprint
import random
import numpy as np

Step 2: Setting the scene

In this code block, we will define the actor’s surroundings by selecting a random background and rotating it by a random amount. This not only defines what can be seen behind the actor, it also defines the type and location of the lighting in the scene, such as house lights, streetlamps, the sun, and so on.

backgrounds = catalog.backgrounds.get()
background = random.choice(backgrounds)
background.rotation = random.uniform(0, 360)
print("The selected background:")
pprint(vars(background))

Step 3: Camera

In this code block, we will define the camera’s location, orientation, and lens parameters. We want the camera to be an ideal distance from our subject’s face: Close enough to see the face clearly, but far enough that the face fits comfortably within frame.

Tip

Use this visualization tool to experiment with camera placement and settings.

camera = assets.Camera(
  name='camera',
  intrinsic_params=assets.IntrinsicParams(
    projection=assets.Projection.PERSPECTIVE,
    resolution_width=1024,
    resolution_height=1024,
    fov_horizontal=10,
    fov_vertical=10,
    wavelength=assets.Wavelength.VISIBLE
  ),
  extrinsic_params=assets.ExtrinsicParams(
    location=assets.Point(x=0., y=-1.6, z=0.12),
    rotation=assets.CameraRotation(yaw=0.0, pitch=0.0, roll=0.0)
  )
)

Step 4: Our Actor

In the following series of code blocks, we will put choose our actor. First, we will choose the identity of our actor based on a randomly selected gender, age, and ethnicity:

gender = random.choices([Gender.MALE, Gender.FEMALE], weights=[1 / 2, 1 / 2])[0]
age = random.choices([Age.YOUNG, Age.ADULT, Age.OLD], weights=[1 / 3, 1 / 3, 1 / 3])[0]
ethnicity = random.choices([Ethnicity.AFRICAN, Ethnicity.NORTH_EUROPEAN, Ethnicity.MEDITERRANEAN, Ethnicity.HISPANIC, Ethnicity.SOUTH_ASIAN, Ethnicity.SOUTHEAST_ASIAN], weights=[1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 6])[0]
human = random.choice(catalog.humans.get(gender=gender, age=age, ethnicity=ethnicity))
print("The selected human:")
pprint(vars(human))

Optional: Change the actor's hair, eyes, and eyebrows

Each actor comes with default values for the other aspects of their identity: their hairstyle and color, eyebrow style and color, and eye color.

Optionally, we can change these values. In this code block we will give our actor a random hair and eyebrow style. The eyebrow style must match the actor’s gender; the hairstyle must match the actor’s gender, age, and ethnicity. We will also apply a random color to the hair, eyebrows, and eyes.

human.head.hair = random.choice(catalog.hair.get(age_group_match=human.attributes.age, gender_match=human.attributes.gender, ethnicity_match=human.attributes.ethnicity))
human.head.eyebrows = random.choice(catalog.eyebrows.get(gender_match=human.attributes.gender))
hair_color = assets.HairColor(melanin=random.random(), redness=random.random(), whiteness = random.random(), roughness=random.uniform(0.15, 0.5), index_of_refraction=random.uniform(1.4, 1.65))
human.head.hair.color_settings = hair_color
human.head.eyes = random.choice(catalog.eyes.get())
print("The selected hair:")
pprint(vars(human.head.hair))
print("\n" + "The selected eyebrows:")
pprint(vars(human.head.eyebrows))

Next we will choose the direction that our actor is looking based on how open or closed the eyes are:

GAZE_MIN_Z = -0.5
GAZE_MAX_Z = 0.3
gaze_direction = np.array([random.uniform(-0.5, 0.5), random.uniform(-1, -0.85), random.uniform(GAZE_MIN_Z, GAZE_MAX_Z)])
human.head.eyes.target_of_gaze = assets.Gaze(distance=random.uniform(0.3, 6), direction=assets.Vector(x=gaze_direction[0], y=gaze_direction[1], z=gaze_direction[2]))
if gaze_direction[2] > 0:
  min_closure = 0
  max_closure = 1 - (gaze_direction[2] / GAZE_MAX_Z)
else:
  min_closure = -gaze_direction[2]
  max_closure = 1
human.head.eyes.eyelid_closure = random.uniform(min_closure, max_closure)
print("The selected eyes:")
pprint(vars(human.head.eyes))

Next we will randomly decide whether our actor should wear an accessory or facial hair (or neither):

# Probability of wearing an accessory (glasses or mask)
ACCESSORY_PROB = 0.5
# Probability that, given the actor is wearing an accessory, that accessory is glasses
GLASSES_PROB = 0.5
# Probability that a male actor without a mask has facial hair
BEARD_PROB = 0.7

glasses = None
mask = None
if random.random() < ACCESSORY_PROB:
  if random.random() < GLASSES_PROB:
    glasses = random.choice(catalog.glasses.get(gender=human.attributes.gender))
    glasses.frame_color = random.choice(list(assets.FrameColor))
    glasses.frame_metalness = random.random()
    glasses.lens_color = random.choice(list(assets.LensColor))
    glasses.lens_reflectivity = random.random()
    glasses.lens_transparency = random.random()
    glasses.position = random.choice(list(assets.GlassesPosition))
    print("The selected glasses:")
    pprint(vars(glasses))
  else:
    mask = random.choice(catalog.masks.get(gender=human.attributes.gender))
    mask.color = random.choice(list(assets.MaskColor))
    mask.texture = random.choice(list(assets.MaskTexture))
    mask.position = random.choice(list(assets.MaskPosition))
    mask.roughness = random.random()
    print("The selected mask:")
    pprint(vars(mask))
if mask is None and human.attributes.gender == attributes.Gender.MALE and random.random() < BEARD_PROB:
  human.head.facial_hair = random.choice(catalog.beards.get())
  human.head.facial_hair.color_settings = human.head.hair.color_settings
  print("\n" + "The selected facial hair:")
  pprint(vars(human.head.facial_hair))
else:
  human.head.facial_hair = None
  if glasses is None and mask is None:
    print("No accessories selected.")

And finally we will bring the actor to life, by choosing the facial expression and the rotation of the head:

human.head.rotation = assets.HeadRotation(yaw=random.uniform(-50, 50), pitch=random.uniform(-20, 20), roll=random.uniform(-10, 10))
human.head.expression = assets.Expression(name=random.choice(list(assets.ExpressionName)), intensity=random.uniform(0.1, 1))
print("The selected head rotation:")
pprint(vars(human.head.rotation))
print("\n" + "The selected facial expression:")
pprint(vars(human.head.expression))

Step 6: Packaging the data request

Now that every aspect of our scene has been defined, we can package it and save it to a JSON file.

DST_JSON_PATH = "data_request.json"
kwargs = {'human': human, 'camera': camera, 'background': background}
datapoints = []
datapoints.append(datapoint_api.create_datapoint(**kwargs))
datapoint_api.dump(assets.DataRequest(datapoints=datapoints),path=DST_JSON_PATH)

The above code creates a file called data_request.json in your Python kernel’s current working directory.

Step 7: (Site only) Download the JSON

If you have been running the code using the interactive kernel in this page, you will need to take one last step to turn the JSON file into a downloadable link.

from IPython.display import HTML
import os, base64

def make_download_link(filepath):
  filename = os.path.basename(filepath)
  with open(filepath, "rb") as f:
    data = base64.b64encode(f.read()).decode()
    return HTML(f'<h4>Click here to download <a href="data:application/binary;base64,{data}" download={filename}>{filename}</a>.</h4>')

filepath = "data_request.json"
make_download_link(filepath)

Step 8: Generating your data

Now that you have your data_request.json file, you can upload it to the platform using the instructions at Generating your data. Our system will start generating your data immediately.