[PYTHON] I came up with a way to make a 3D model from a photo.

Domo is Ksuke. In Part 05, when I came up with a way to create a 3D model from a photo, I will reduce the number of faces. Click here for Part 4 https://qiita.com/Ksuke/items/144c06f128b015b001dd

* Caution * </ b> This article only gives the end of what I came up with and tried, so it could end up with abrupt material or Bad End.

Try

Procedure </ b>

  1. Surface reduction

This is all this time (it's a secret that the number of characters in the article is smaller than usual because what I wanted to do was contained in one method despite the difficulty in investigating and implementing it).

~~ The code here and there is the one summarized at the end. There are only two sources ~~, but as usual, they are also posted at the end.

1. Surface reduction

The reduction of the surface is done by using the function of blender. What kind of function is Decimate among the modifiers available in Blender's object mode. If you specify some parameters and execute it, the number of faces will be reduced. As a bonus, we are also deleting vertices that are no longer used as a result of reducing the number of faces.

Surface reduction




#Function to reduce the number of faces
def faceReduction(obj,modifierName="faceReductionDecimate"): 
        
    #Change the change object to be active
    bpy.context.view_layer.objects.active = obj

    #Move to object mode
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    #Added modifier, face reduction
    bpy.ops.object.modifier_add(type='DECIMATE')

    #Give it a name
    bpy.context.object.modifiers["Decimate"].name = modifierName

    #Specify the reduction method
    bpy.context.object.modifiers[modifierName].decimate_type = "COLLAPSE"

    #Specify reduction rate
    bpy.context.object.modifiers[modifierName].ratio = 0.05

    #Run Decimate
    bpy.ops.object.modifier_apply(modifier = modifierName)

    #Move to edit mode
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    #Delete vertices with no connection
    bpy.ops.mesh.delete_loose()

#Add object(Until the last time, I added objects only for confirmation.)
me,obj = addObj(coords=coords,faces=faces,name = "porigon",offset=[-50,-50,-50])

#Surface reduction
faceReduction(obj)

Operation check

Finally, let's see if the code works fine and this time how much the faces and vertices have been reduced.

1. Displaying objects

If the object is displayed like this, it is successful. キャプチャ.PNG As you can see, the faces and vertices are also reduced.

2. Number of face and vertex reductions

Add a code like this after the display / reduction to display the number of faces and vertices before and after the reduction.

For checking the number of vertices and faces



#Addition of confirmation object before face reduction
originMe,originObj = addObj(coords=coords,faces=faces,name = "originPorigon",offset=[-50,-50,-50])

#Convert the object after reduction into a format that makes it easy to manipulate each data
bm=bmesh.from_edit_mesh(obj.data)

#Switch to edit mode again
bpy.ops.object.mode_set(mode='EDIT', toggle=False)

#Convert objects before reduction into a format that makes it easy to manipulate each data
originBm=bmesh.from_edit_mesh(originObj.data)

#Shows the number of faces and vertices of two objects
print("originObj:")
print("  vertsLen:{}".format(len(originBm.verts)))
print("  facesLen:{}".format(len(originBm.faces)))
print()
print("faceReductedObj:")
print("  vertsLen:{}".format(len(bm.verts)))
print("  facesLen:{}".format(len(bm.faces)))
print()

The output result looks like this.

originObj:
  vertsLen:13279
  facesLen:26590

faceReductedObj:
  vertsLen:594
  facesLen:1328

It's about 1/20. Too much data in the original object. .. ..

next?

At last it looks like that, but I miss the color, so I will paste the image (the one used to generate the model) as a texture.

Code summary

If you add it after the previous code, it should work.

Function

Code summary(Function)


#Function to reduce the number of faces
def faceReduction(obj,modifierName="faceReductionDecimate"): 
        
    #Change the change object to be active
    bpy.context.view_layer.objects.active = obj

    #Move to object mode
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    #Added modifier, face reduction
    bpy.ops.object.modifier_add(type='DECIMATE')

    #Give it a name
    bpy.context.object.modifiers["Decimate"].name = modifierName

    #Specify the reduction method
    bpy.context.object.modifiers[modifierName].decimate_type = "COLLAPSE"

    #Specify reduction rate
    bpy.context.object.modifiers[modifierName].ratio = 0.05

    #Run Decimate
    bpy.ops.object.modifier_apply(modifier = modifierName)

    #Move to edit mode
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    #Delete vertices with no connection
    bpy.ops.mesh.delete_loose()

Execution code

Code summary(Execution code)



#Add object
me,obj = addObj(coords=coords,faces=faces,name = "porigon",offset=[-50,-50,-50])

#Surface reduction
faceReduction(obj)

print("step05:face reduction success\n")


#For confirmation display below(It has nothing to do with the main flow, so it will probably disappear in the next round)

#Addition of confirmation object before face reduction
originMe,originObj = addObj(coords=coords,faces=faces,name = "originPorigon",offset=[-50,-50,-50])

#Convert the object after reduction into a format that makes it easy to manipulate each data
bm=bmesh.from_edit_mesh(obj.data)

#Switch to edit mode again
bpy.ops.object.mode_set(mode='EDIT', toggle=False)

#Convert objects before reduction into a format that makes it easy to manipulate each data
originBm=bmesh.from_edit_mesh(originObj.data)

#Shows the number of faces and vertices of two objects
print("originObj:")
print("  vertsLen:{}".format(len(originBm.verts)))
print("  facesLen:{}".format(len(originBm.faces)))
print()
print("faceReductedObj:")
print("  vertsLen:{}".format(len(bm.verts)))
print("  facesLen:{}".format(len(bm.faces)))
print()

Recommended Posts