cnr-isti-vclab / PyMeshLab

The open source mesh processing python library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ms.compute_normal_per_vertex IGNORED

TokyoWarfare opened this issue · comments

Hi, I've the feeling that the

"ms.compute_normal_per_vertex(weightmode=1)" command is not working.

I tested in in UI version, works great, removes all the here and there faces that are not properly oriented. I generated the pymeshlab with the super convienent button that builds up the command.

But the thing is that the output mesh seems unprocesed, and if I open in UI version and run the command manually via interface all the issues are fixed.

Here is the whole script

`import os
import pymeshlab

input_folder = r'E:\LIDAR_JAPAN\MMS_14_Prototype_4\MMS\04_RoadMesh\04_Texturing\01_DATA_SOURCE_POINT_CLOUDS\00_color'
output_folder = r'E:\LIDAR_JAPAN\MMS_14_Prototype_4\MMS\04_RoadMesh\04_Texturing\01_DATA_SOURCE_POINT_CLOUDS\03_Normals\HD_RoadMesh'
depth = 13

print(f"Input folder: {input_folder}")
print(f"Output folder: {output_folder}")
print(f"Depth value: {depth}")

def compute_average_normal(ms):
normals = ms.current_mesh().vertex_normal_matrix()
avg_normal = normals.mean(axis=0)
return avg_normal

def mesh_point_clouds(input_folder, output_folder, depth):
if not os.path.exists(input_folder):
raise FileNotFoundError(f"The input folder '{input_folder}' does not exist.")

if not os.path.exists(output_folder):
    os.makedirs(output_folder)
else:
    print(f"Output folder '{output_folder}' already exists. Files may be overwritten.")

files = [f for f in os.listdir(input_folder) if f.endswith('.ply')]
total_files = len(files)
print(f"Total files to be processed: {total_files}")

for i, file in enumerate(files, 1):
    input_path = os.path.join(input_folder, file)
    output_path = os.path.join(output_folder, file)
    
    print(f"[{i}/{total_files}] Loading file: {file}")

    ms = pymeshlab.MeshSet()
    ms.load_new_mesh(input_path)
    
    # Compute normals for the point cloud
    print(f"[{i}/{total_files}] Computing normals for: {file}")
    try:
        ms.compute_normal_for_point_clouds(k=20, smoothiter=0)
    except pymeshlab.PyMeshLabException as e:
        print(f"Failed to compute normals for {file}: {e}")
        continue
    
    # Perform surface reconstruction
    print(f"[{i}/{total_files}] Generating surface reconstruction for: {file}")
    try:
        ms.generate_surface_reconstruction_screened_poisson(depth=depth)
    except pymeshlab.PyMeshLabException as e:
        print(f"Failed to process {file}: {e}")
        continue
    
    # Delete input point cloud to force normal computation on the mesh
    #os.remove(input_path)

    # Print number of faces before recomputing normals
    num_faces = ms.current_mesh().face_number()
    print(f"[{i}/{total_files}] Number of faces before recomputing normals: {num_faces}")

    # Recompute normals for the reconstructed mesh
    print(f"[{i}/{total_files}] Recomputing normals for: {file}")
    try:
        ms.compute_normal_per_vertex(weightmode=1)
    except pymeshlab.PyMeshLabException as e:
        print(f"Failed to recompute normals for {file}: {e}")
        continue
    
    # Check the average normal direction
    avg_normal = compute_average_normal(ms)
    if avg_normal[2] < 0:  # If the z-component is negative, normals are pointing downwards
        print(f"[{i}/{total_files}] Inverting normals for: {file}")
        try:
            ms.meshing_invert_face_orientation()
        except pymeshlab.PyMeshLabException as e:
            print(f"Failed to invert normals for {file}: {e}")
            continue
    
    # Save the mesh
    ms.save_current_mesh(output_path)
    
    print(f"[{i}/{total_files}] Processed {file} and saved to {output_path}")

mesh_point_clouds(input_folder, output_folder, depth)
`

I've uploaded a sample input file
https://drive.google.com/file/d/1RzwmuURgNsWdC3FUmrXaRfOUxQVictP-/view?usp=sharing

I would love to heard wetehr this is the case or it is me that I'md doing something wrong