1

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)
Ray Mairlot
  • 29,192
  • 11
  • 103
  • 125
ron653
  • 43
  • 1
  • 8
  • 1
    Ideal candidate for running blender in background mode. blender --help in command line to see endless options. https://blender.stackexchange.com/questions/131052/how-to-render-in-command-line 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 https://blender.stackexchange.com/questions/7358/python-performance-with-blender-operators – batFINGER Jan 22 '20 at 14:57
  • Thanks, running in background mode solve the issue – ron653 Jan 23 '20 at 12:27

1 Answers1

1

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)
ron653
  • 43
  • 1
  • 8