Skip to content

Commit

Permalink
extended scripts folder
Browse files Browse the repository at this point in the history
  • Loading branch information
lcmrl committed Nov 21, 2024
1 parent d1a59d1 commit cef98cb
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 0 deletions.
27 changes: 27 additions & 0 deletions scripts/copy_images_no_exif.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import argparse
import os
import cv2

def copy_images_no_exif(input_folder, output_folder):
if not os.path.exists(output_folder):
os.makedirs(output_folder)

for filename in os.listdir(input_folder):
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tiff')):
img_path = os.path.join(input_folder, filename)
img = cv2.imread(img_path)
if img is not None:
output_path = os.path.join(output_folder, filename)
cv2.imwrite(output_path, img)
print(f"Copied {filename} to {output_folder}")

def main():
parser = argparse.ArgumentParser(description="Copy images without EXIF data")
parser.add_argument('input_folder', type=str, help="Folder with input images")
parser.add_argument('output_folder', type=str, help="Folder to save output images")
args = parser.parse_args()

copy_images_no_exif(args.input_folder, args.output_folder)

if __name__ == "__main__":
main()
77 changes: 77 additions & 0 deletions scripts/keypoint_density_evaluation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import sqlite3
import argparse
from pathlib import Path

def pair_id_to_image_ids(pair_id):
image_id2 = pair_id % 2147483647
image_id1 = (pair_id - image_id2) / 2147483647
return image_id1, image_id2

def ExportMatches(
database_path: Path,
min_num_matches: int,
output_path: Path,
width: int,
height: int,
) -> None:

if not output_path.exists():
print("Output folder does not exist")
quit()

connection = sqlite3.connect(database_path)
cursor = connection.cursor()

images = {}
pairs = []

cursor.execute("SELECT image_id, name FROM images")
for row in cursor:
image_id = row[0]
name = row[1]
images[image_id] = name

cursor.execute("SELECT pair_id, rows FROM two_view_geometries")
for row in cursor:
pair_id = row[0]
n_matches = row[1]
id_img1, id_img2 = pair_id_to_image_ids(pair_id)
id_img1, id_img2 = int(id_img1), int(id_img2)
img1 = images[id_img1]
img2 = images[id_img2]

if n_matches >= min_num_matches:
pairs.append((img1, img2))

with open(output_path / "pairs.txt", "w") as f:
n_pairs = len(pairs)
n_brute = 0
N = len(images.keys())
for x in range(1, N):
n_brute += N-x
print(f"n_pairs/n_brute: {n_pairs} / {n_brute}")

for pair in pairs:
f.write(f"{pair[0]} {pair[1]}\n")

connection.close()


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Export pairs in a txt file from a COLMAP database."
)
parser.add_argument("-d", "--database", type=Path, required=True, help="Path to COLMAP database.")
parser.add_argument("-m", "--min_n_matches", type=int, required=True, help="Min number of matches that a pair should have after geometric verification.")
parser.add_argument("-w", "--width", type=int, required=True, help="Image width.")
parser.add_argument("-e", "--height", type=int, required=True, help="Image height.")
parser.add_argument("-o", "--output", type=Path, required=True, help="Path to output folder.")
args = parser.parse_args()

ExportMatches(
database_path=args.database,
min_num_matches=args.min_n_matches,
output_path=args.output,
width=args.width,
height=args.height,
)
105 changes: 105 additions & 0 deletions scripts/lidar_optimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import tqdm
import random
import argparse
import pycolmap
import open3d as o3d
import numpy as np
from scipy.spatial import cKDTree


def main():
parser = argparse.ArgumentParser(description='Process point cloud and colmap model folder')
parser.add_argument('point_cloud', type=str, help='Path to the point cloud file')
parser.add_argument('colmap_folder', type=str, help='Path to the folder containing the colmap model')
parser.add_argument('output_folder', type=str, help='Path to the output folder')
parser.add_argument('camera_pos', type=str, help='Path to camera positions')

args = parser.parse_args()
point_cloud_path = args.point_cloud
colmap_folder_path = args.colmap_folder
output_folder = args.output_folder
camera_pos_path = args.camera_pos

constraints = {}
reconstruction = pycolmap.Reconstruction(colmap_folder_path)
point_cloud = o3d.io.read_point_cloud(point_cloud_path)
points_ply = np.asarray(point_cloud.points)
kdtree = cKDTree(points_ply)

#camera_pos = {}
#with open(camera_pos_path, 'r') as f:
# lines = f.readlines()
# for line in lines:
# line = line.strip()
# image, x, y, z, _ = line.split('\t', 4)
# for img_id, img in reconstruction.images.items():
# if img.name == image:
# camera_pos[img_id] = np.array([float(x), float(y), float(z)])
# break
#
#scale, rotation, translation = pycolmap.align_reconstruction(reconstruction, camera_pos);quit()

point3Ds = []
for point3D_id in reconstruction.points3D:
point3Ds.append(point3D_id)

random_point3D_ids = random.sample(point3Ds, 200)

for point3D_id in random_point3D_ids:
point3D = reconstruction.points3D[point3D_id]
#print(f"3D Point {point3D_id} coordinates: {point3D.xyz}")

projections = []
for image in reconstruction.images.values():
# For each image, check if it observes the 3D point
for feature_idx, point2D in enumerate(image.points2D):
if point2D.has_point3D and point2D.point3D_id == point3D_id:
# Add the projection information: image ID and 2D point coordinates
projections.append((image.image_id, point2D.xy))
#print(f"Image {image.image_id}: Projected 2D point (x, y) = {point2D.xy}")

constraints[point3D_id] = {
'3D_tiepoint': point3D.xyz,
'projections': projections,
'lidar_point': None,
}

# Export to txt file
with open(f'{output_folder}/constraints.txt', 'w') as f:
for point3D_id in random_point3D_ids:
for image_id, point2D in constraints[point3D_id]['projections']:
image = reconstruction.images[image_id]
f.write(f"{point3D_id},{image.name[:-4]},{point2D[0]},{point2D[1]}\n")


query_points = np.empty((0, 3))
ids = []
for point3D_id in random_point3D_ids:
x = constraints[point3D_id]['3D_tiepoint'][0]
y = constraints[point3D_id]['3D_tiepoint'][1]
z = constraints[point3D_id]['3D_tiepoint'][2]
query_points = np.vstack((query_points, np.array([float(x), float(y), float(z)])))
ids.append(point3D_id)

distances, indices = kdtree.query(query_points)

for i, (point3D_id, index) in enumerate(zip(ids, indices)):
nearest_point = points_ply[index]
constraints[point3D_id]['lidar_point'] = nearest_point

with open(f'{output_folder}/points.txt', 'w') as f:
for point3D_id in random_point3D_ids:
x_photogram = float(constraints[point3D_id]['3D_tiepoint'][0])
y_photogram = float(constraints[point3D_id]['3D_tiepoint'][1])
z_photogram = float(constraints[point3D_id]['3D_tiepoint'][2])
x_lidar = float(constraints[point3D_id]['lidar_point'][0])
y_lidar = float(constraints[point3D_id]['lidar_point'][1])
z_lidar = float(constraints[point3D_id]['lidar_point'][2])
norm = ((x_photogram-x_lidar)**2+(y_photogram-y_lidar)**2+(z_photogram-z_lidar)**2)**0.5
print(norm)
if norm < 0.20:
f.write(f"{point3D_id},{x_lidar},{y_lidar},{z_lidar}\n")


if __name__ == '__main__':
main()

0 comments on commit cef98cb

Please sign in to comment.