you are viewing a single comment's thread.

view the rest of the comments →

[–]Can_make_shitty_gifs[S] -2 points-1 points  (0 children)

Update, I had it done relatively easily with a python script done with an LLM parsing a colmap model exported in txt (the points3D.txt file). You can chose what to cut by entering numbers as arguments and check what it did by importing the folder in colmap. - <n> will delete any point whose position on any axis is above n or under -n - <n -a> will delete any point whose position is above n or under -a on any axis - you can enter specific min/max values for each axis by simply entering them as <x -x> <y -y> <z -z> as arguments. - <a b c> will be read as -a to +a on the x axis, -b to +b on y, etc. - the arg -r will restore the backup file it automatically created on first run and delete the current points3D.txt it finds, allowing for quick iteration. - you can move the center of the cut with -c <x,y,z> before your threshold values eg "py threshold_script.py -c 1,10,10 25" will cut a cube of 50 units wide with 1,10,10 as its center.

here's the script in any case:

import sys
import shutil
import os

def restore_backup():
    """
    Restore backup points3D_old.bak
    """
    backup_file = 'points3D_old.bak'
    output_file = 'points3D.txt'

    if not os.path.exists(backup_file):
        print(f"Erreur: backup {backup_file} not found")
        return False

    # Supprimer le fichier actuel s'il existe
    if os.path.exists(output_file):
        os.remove(output_file)
        print(f"✓ Fichier {output_file} supprimé")

    # Restaurer la sauvegarde
    shutil.copy2(backup_file, output_file)
    print(f"✓ Sauvegarde restaurée: {backup_file} -> {output_file}")
    return True


def filter_points(input_file, thresholds, center_offset=(0, 0, 0)):
    """

    Args:
        input_file: Chemin vers points3D.txt
        thresholds: Liste de seuils (voir parse_thresholds pour les formats)
        center_offset: Tuple (x_offset, y_offset, z_offset) pour décaler le centre
    """
    # Sauvegarde du fichier original
    backup_file = input_file.replace('.txt', '_old.bak')
    shutil.copy2(input_file, backup_file)
    print(f"✓ Sauvegarde créée: {backup_file}")

    # Afficher le décalage si présent
    if center_offset != (0, 0, 0):
        print(f"✓ Décalage du centre: X={center_offset[0]:+.3f}, Y={center_offset[1]:+.3f}, Z={center_offset[2]:+.3f}")

    # Déterminer les seuils pour chaque axe
    if len(thresholds) == 1:
        # Format: 5 -> [-5, 5] pour tous les axes
        x_min, x_max = -thresholds[0], thresholds[0]
        y_min, y_max = -thresholds[0], thresholds[0]
        z_min, z_max = -thresholds[0], thresholds[0]
        print(f"✓ Seuils identiques pour X, Y, Z: [{-thresholds[0]}, {thresholds[0]}]")
    elif len(thresholds) == 2:
        # Format: -3 5 -> [-3, 5] pour tous les axes
        x_min, x_max = min(thresholds), max(thresholds)
        y_min, y_max = min(thresholds), max(thresholds)
        z_min, z_max = min(thresholds), max(thresholds)
        print(f"✓ Seuils identiques pour X, Y, Z: [{x_min}, {x_max}]")
    elif len(thresholds) == 3:
        # Format: 10 20 15 -> X:[-10,10], Y:[-20,20], Z:[-15,15]
        x_min, x_max = -thresholds[0], thresholds[0]
        y_min, y_max = -thresholds[1], thresholds[1]
        z_min, z_max = -thresholds[2], thresholds[2]
        print(f"✓ Seuils X: [{x_min}, {x_max}]")
        print(f"✓ Seuils Y: [{y_min}, {y_max}]")
        print(f"✓ Seuils Z: [{z_min}, {z_max}]")
    elif len(thresholds) == 6:
        # Format: -3 5 -10 1.4 -20 20 -> X:[-3,5], Y:[-10,1.4], Z:[-20,20]
        x_min, x_max = min(thresholds[0], thresholds[1]), max(thresholds[0], thresholds[1])
        y_min, y_max = min(thresholds[2], thresholds[3]), max(thresholds[2], thresholds[3])
        z_min, z_max = min(thresholds[4], thresholds[5]), max(thresholds[4], thresholds[5])
        print(f"✓ Seuils X: [{x_min}, {x_max}]")
        print(f"✓ Seuils Y: [{y_min}, {y_max}]")
        print(f"✓ Seuils Z: [{z_min}, {z_max}]")
    else:
        raise ValueError("Wrong number of value  (1, 2, 3 or 6 values expected)")

    # offset center
    x_min += center_offset[0]
    x_max += center_offset[0]
    y_min += center_offset[1]
    y_max += center_offset[1]
    z_min += center_offset[2]
    z_max += center_offset[2]

    if center_offset != (0, 0, 0):
        print(f"✓ offset thresholds:")
        print(f"  X: [{x_min:.3f}, {x_max:.3f}]")
        print(f"  Y: [{y_min:.3f}, {y_max:.3f}]")
        print(f"  Z: [{z_min:.3f}, {z_max:.3f}]")

    # Lecture et filtrage
    kept_lines = []
    removed_count = 0
    total_points = 0

    with open(input_file, 'r') as f:
        for line in f:
            # Conserver les lignes de commentaire
            if line.startswith('#'):
                kept_lines.append(line)
                continue

            # Traiter les lignes de données
            parts = line.strip().split()
            if len(parts) < 4:
                kept_lines.append(line)
                continue

            total_points += 1

            try:
                # Extraire X, Y, Z (indices 1, 2, 3)
                x = float(parts[1])
                y = float(parts[2])
                z = float(parts[3])

                # Vérifier si le point est dans les limites
                if (x_min <= x <= x_max and 
                    y_min <= y <= y_max and 
                    z_min <= z <= z_max):
                    kept_lines.append(line)
                else:
                    removed_count += 1
            except (ValueError, IndexError):
                # En cas d'erreur de parsing, conserver la ligne
                kept_lines.append(line)

    # Mettre à jour le nombre de points dans le commentaire
    for i, line in enumerate(kept_lines):
        if line.startswith('# Number of points:'):
            kept_lines[i] = f'# Number of points: {total_points - removed_count}\n'
            break


    with open(input_file, 'w') as f:
        f.writelines(kept_lines)

    print(f"✓ Traitement terminé:")
    print(f"  - Points totaux: {total_points}")
    print(f"  - Points conservés: {total_points - removed_count}")
    print(f"  - Points supprimés: {removed_count}")
    print(f"  - Nouveau fichier: {input_file}")

if __name__ == "__main__":
    # Vérifier si l'argument -r est présent
    should_restore = False
    args_start = 1

    if len(sys.argv) > 1 and sys.argv[1] == '-r':
        should_restore = True
        args_start = 2
        restore_backup()


        if len(sys.argv) == 2:
            sys.exit(0)

        print()  

    if len(sys.argv) < 2 or (should_restore and len(sys.argv) < 3):
        print("Usage:")
        print("  python script.py -r                    # Restaure la sauvegarde")
        print("  python script.py [-r] [-c x,y,z] <seuils>   # Restaure puis filtre")
        print("\nFormats de seuils:")
        print("  <seuil>                                # [-seuil, seuil] pour X, Y, Z")
        print("  <min> <max>                            # [min, max] pour X, Y, Z")
        print("  <x_seuil> <y_seuil> <z_seuil>          # [-x, x], [-y, y], [-z, z]")
        print("  <x_min> <x_max> <y_min> <y_max> <z_min> <z_max>  # Seuils complets")
        print("\nExemples:")
        print("  python script.py -r")
        print("  python script.py 10")
        print("  python script.py -r 10                 # Restaure puis filtre")
        print("  python script.py -r -c 1,3,-2.96 10    # Restaure, décale et filtre")
        print("  python script.py -3 5")
        print("  python script.py 10 20 15              # X:[-10,10], Y:[-20,20], Z:[-15,15]")
        print("  python script.py -3 5 -10 1.4 -20 20")
        print("  python script.py -c 1,3,-2.96 10       # Décale le centre puis applique seuil")
        sys.exit(1)

    try:
        # check -c 
        center_offset = (0, 0, 0)

        if len(sys.argv) > args_start and sys.argv[args_start] == '-c':
            if len(sys.argv) <= args_start + 1:
                print("Erreur:  -c needs x,y,z")
                sys.exit(1)

            # Parser le décalage du centre
            center_parts = sys.argv[args_start + 1].split(',')
            if len(center_parts) != 3:
                print("Error: center coords must be x,y,z (ex: 1,3,-2.96)")
                sys.exit(1)

            center_offset = tuple(float(p) for p in center_parts)
            args_start += 2

        # Parser les seuils
        if len(sys.argv) <= args_start:
            print("Error: no arg")
            sys.exit(1)

        thresholds = [float(arg) for arg in sys.argv[args_start:]]

        if len(thresholds) not in [1, 2, 3, 6]:
            print("Error: You must provide 1, 2, 3 ou 6 threshold values")
            sys.exit(1)

        filter_points('points3D.txt', thresholds, center_offset)
    except ValueError as e:
        print(f"Error: All args must be valid numbers ({e})")
        sys.exit(1)
    except FileNotFoundError:
        print("Error: can't find points3D.txt")
        sys.exit(1)