DIYer22 / bpycv

Computer vision utils for Blender (generate instance annoatation, depth and 6D pose by one line code)
MIT License
464 stars 58 forks source link

Instance map incorrect when objects are converted from duplicates #45

Closed wish2023 closed 1 year ago

wish2023 commented 1 year ago

Hi, thanks for the awesome blender utils!

I am trying to convert particle emissions to objects and then segment them, but separate objects are considered to be part of the same instance. Here's the minimal code that will generate the issue

import bpy
import bpycv
import cv2
from bpy import context
import numpy as np

# Scene setup
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
bpy.ops.mesh.primitive_cube_add(size=1)
bpy.ops.mesh.primitive_plane_add(size=20,)
bpy.ops.object.camera_add(location=(0, 0, 80), rotation=(0, 0, 0))
bpy.context.scene.camera = context.object
bpy.ops.object.light_add(type='SUN')
cube = bpy.data.objects["Cube"]
plane = bpy.data.objects["Plane"]

ps = plane.modifiers.new("part", 'PARTICLE_SYSTEM')
psys = plane.particle_systems[ps.name]
psys.settings.type = "HAIR"
psys.settings.use_advanced_hair = True
psys.settings.count = 2 # Creating two hair emissions of cube
psys.settings.instance_object = cube # Creating two hair emissions of cube
psys.settings.render_type = "OBJECT"
psys.settings.particle_size = 1

plane.select_set(True)
bpy.ops.object.duplicates_make_real() # Make instanced objects attached to this object real

# Render using bpycv
bpy.data.objects["Cube.001"]["inst_id"] = 1001
bpy.data.objects["Cube.002"]["inst_id"] = 1002
result = bpycv.render_data()
cv2.imwrite("demo.jpg", result["image"][..., ::-1])
cv2.imwrite("demo-seg.png", np.uint16(result["inst"]))

The inst_id are correctly shown in the UI (One cube has inst_id = 1001 and second has inst_id = 1002, but all cubes seem to be in the same instance in demo-seg.png (all cubes have inst_id = 1002)

Screenshot from 2022-09-05 15-40-59 Screenshot from 2022-09-05 15-59-17

DIYer22 commented 1 year ago

objects["Cuda"] objects["Cuda.001"] and objects["Cuda.002"] have same obj.data, that mean they has same obj.data.materials.

Fix by adding those code

bpy.data.objects["Cube.001"].data = bpy.data.objects["Cube"].data.copy()
bpy.data.objects["Cube.002"].data = bpy.data.objects["Cube"].data.copy()
result = bpycv.render_data()