1
$\begingroup$

I want to render about 2000 scenes. It goes well with the following script, until about rendering the 200th scene, then I get "killed" in the terminal and the process is dead. I'm suspect there is some kind of bug in my code, maybe I'm not free memory correctly? Any ideas how to fix it?

import bpy
import os
import pickle
import math
import random


def deg_to_rad(deg):
    return deg / 180 * math.pi


scenarios = pickle.load(open("./scenarios0.p", 'rb'))

NUM_MAGES = 2000
context = bpy.context


d = './model_collection/'
my_dirs  = [os.path.join(d, o) for o in os.listdir(d) if os.path.isdir(os.path.join(d,o))]
num_models = len(my_dirs)


for i in range(NUM_MAGES):
    old_objs = set(context.scene.objects)
    my_c = scenarios[i]
    for j in range(len(my_cars)):
        rand_idx = random.randint(0, num_models-1)
        file_loc = os.path.join(my_dirs[rand_idx],'model.obj')
        print(file_loc)
        cur_objs = set(context.scene.objects)
        bpy.ops.import_scene.obj(filepath=file_loc)

        imported_obj = set(context.scene.objects) - cur_objs

        for obj in imported_obj:
            obj.scale = (5.3, 5.3, 5.3)
            obj.rotation_euler = (deg_to_rad(90), 0, deg_to_rad(my_c[j][1])) #Roll, Pitch, Yaw 
            obj.location.x = my_cars[j][0][0]
            obj.location.y = my_cars[j][0][1]

    scene = bpy.context.scene
    scene.render.filepath = './renders/' + str(i) + '.png'
    bpy.ops.render.render("EXEC_DEFAULT", write_still=True)

    to_delete_objs = set(context.scene.objects) - old_objs
    for obj in to_delete_objs :
        bpy.data.objects.remove(obj)
$\endgroup$
2
  • 1
    $\begingroup$ Ideal candidate for running blender in background mode. blender --help in command line to see endless options. blender.stackexchange.com/questions/131052/… Write a (python) shell script creating blender command to open an empty file (or with cam setup etc. ) import and render 2000 times rather than hitting what I suspect is this ol' chestnut issue blender.stackexchange.com/questions/7358/… $\endgroup$
    – batFINGER
    Jan 22 '20 at 14:57
  • $\begingroup$ Thanks, running in background mode solve the issue $\endgroup$
    – ron653
    Jan 23 '20 at 12:27
1
$\begingroup$

I ran the script at the background using simple python script:

import os
import sys

if __name__ == '__main__':
    blender = sys.argv[-4]
    amount = int(sys.argv[-3])
    scene = sys.argv[-2]
    script = sys.argv[-1]

    os.system('rm -rf ./temp_idx.p')
    for i in range(amount):
        os.system(blender + ' ' + scene + ' --background -P ' + script)

To overcome the loop issue (how can I keep the correct index) I dumped the index to a file and read it each time:

import bpy
import os
import pickle
import math
import random
import sys

def deg_to_rad(deg):
    return deg / 180 * math.pi


scenarios = pickle.load(open("./scenarios0.p", 'rb'))

START = 0

context = bpy.context

try:
    idx = pickle.load(open("./temp_idx.p", 'rb'))
    pickle.dump(idx+1, open("./temp_idx.p", "wb"))
except FileNotFoundError:
    idx = START
    pickle.dump(idx+1, open("./temp_idx.p", "wb"))


try:
    my_dirs, num_models = pickle.load(open("./temp_dirs.p", 'rb'))
except FileNotFoundError:
    d = './car_collection/'
    my_dirs = [os.path.join(d, o) for o in os.listdir(d) if os.path.isdir(os.path.join(d, o))]
    my_dirs.sort()
    num_models = len(my_dirs)
    pickle.dump((my_dirs, num_models), open("./temp_dirs.p", "wb"))

old_objs = set(context.scene.objects)
my_cars = scenarios[idx]
for j in range(len(my_cars)):
    rand_idx = random.randint(0, num_models - 1)
    file_loc = os.path.join(my_dirs[rand_idx], 'model.obj')
    cur_objs = set(context.scene.objects)
    bpy.ops.import_scene.obj(filepath=file_loc)

    imported_obj = set(context.scene.objects) - cur_objs

    for obj in imported_obj:
        obj.scale = (5.3, 5.3, 5.3)
        obj.rotation_euler = (deg_to_rad(90), 0, deg_to_rad(my_cars[j][1]))  # Roll, Pitch, Yaw 
        obj.location.x = my_cars[j][0][0]
        obj.location.y = my_cars[j][0][1]

scene = bpy.context.scene
scene.render.filepath = './renders_wed/' + str(idx) + '.png'
# bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)
bpy.ops.render.render("EXEC_DEFAULT", write_still=True)

to_delete_objs = set(context.scene.objects) - old_objs
for obj in to_delete_objs:
    bpy.data.objects.remove(obj)
$\endgroup$
2
  • 1
    $\begingroup$ Thanks for taking the time to make an answer. $\endgroup$
    – batFINGER
    Jan 23 '20 at 12:38
  • 1
    $\begingroup$ Can also use math.radians(deg) $\endgroup$
    – batFINGER
    Jan 23 '20 at 14:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.