OpenDroneMap-ODM/knnMatch_exif.py

120 wiersze
4.7 KiB
Python
Executable File

import os
import math
import subprocess
# Purpose:
# Preselect camera pairs for meature matching based by using GPS exif data.
def preselect_pairs(utm_extractor_path, image_list, k_distance, use_knn_mode = True, verbose = False):
# Parameterss:
# utm_extractor_path: Path to the odm utm_extraction program that parses exif data.
# images_path: Path to the folder containing the images.
# k_distance: Nearest neighbor count in case of use_knn_mode = True, otherwise
# the minimum distance between cameras to be matched.
# use_knn_mode: True if knn mode is used to preselect matches, False for distance thresholding.
# Temporary files
image_list_file = 'image_list_tmp.txt'
utm_coord_file = 'utm_coord_tmp.txt'
# Parse the list of files with successfullt detectd points.
image_folder = ""
filenames = []
with open(image_list, 'r') as keypoint_file:
first_line = keypoint_file.readline()
image_folder = first_line[:first_line.rfind("/")]
keypoint_file.seek(0)
for line in keypoint_file:
filename = line[line.rfind("/")+1:line.rfind(".")]
filename += ".jpg"
filenames.append(filename)
data = open(image_list_file, "w")
for filename in filenames:
data.write("%s\n" % filename)
data.close()
# Define call parameters for calling the odm_extract_utm module
utm_cmd = ''
if verbose:
utm_cmd = [utm_extractor_path, '-verbose', '-imagesPath', image_folder, \
'-imageListFile', image_list_file, '-outputCoordFile', utm_coord_file]
else:
utm_cmd = [utm_extractor_path, '-imagesPath', image_folder, '-imageListFile', \
image_list_file, '-outputCoordFile', utm_coord_file]
# Perform UTM extraction
utm_process = subprocess.Popen(utm_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output, err = utm_process.communicate()
# Check return code
if utm_process.returncode != 0:
print "Error when performing utm_extraction, dumping log file:"
print output
os.remove(image_list_file)
return []
# Parse odm_extract_utm output
coords = []
with open('utm_coord_tmp.txt', 'r') as coord_file:
# Skip header lines
next(coord_file)
next(coord_file)
for line in coord_file:
first_space = line.find(' ')
second_space = first_space + line[first_space+1:].find(' ')
xCoord = float(line[0: first_space])
yCoord = float(line[first_space+1: second_space+1])
coords.append([xCoord, yCoord])
# Calculate distances between camera pairs
distances = []
for xo,yo in coords:
distances.append([])
for xi, yi in coords:
current_image = len(distances)
xDist = xo-xi
yDist = yo-yi
distance = math.sqrt(xDist*xDist + yDist*yDist)
current_image = len(distances[-1])
distances[-1].append([current_image, distance, False])
distances[-1].sort(key=lambda tup: tup[1])
# Select matched pairs and make there are no doubles
matched_pairs = []
if use_knn_mode:
# Make sure that image count > k
if len(coords) <= k_distance:
print "Warning, k >= image count, the result will be equivalent to exhaustive matching"
k_distance = len(coords)-1
for outer_index, sorted_list in enumerate(distances):
# Skip first element as distance will always be zero
for sorted_index in xrange(1, k_distance+1):
image_index, distance, dummy = distances[outer_index][sorted_index]
is_added = distances[outer_index][image_index][2]
if not is_added:
matched_pairs.append([outer_index, image_index])
distances[outer_index][image_index][2] = True
distances[image_index][outer_index][2] = True
else: # Distance mode
for outer_index, sorted_list in enumerate(distances):
# Skip first element as distance will always be zero
for image_index, distance, dummy in sorted_list:
if outer_index == image_index:
continue
if distance > k_distance:
break
is_added = distances[outer_index][image_index][2]
if not is_added:
matched_pairs.append([outer_index, image_index])
distances[outer_index][image_index][2] = True
distances[image_index][outer_index][2] = True
# Remove temporary files
os.remove(image_list_file)
os.remove(utm_coord_file)
return matched_pairs