def check_task(image,
               hashes,
               RESOLUTION_THRESHOLD,
               BLURRINESS_THRESHOLD,
               under_res,
               too_blurry,
               hashing=True):
    if image not in hashes:
        img = cv2.imread(image, cv2.IMREAD_GRAYSCALE)

        # Find image size in pixels, if too low, move to under resolution folder.
        height, width = img.shape
        val = width * height
        if val < RESOLUTION_THRESHOLD:
            move(image, under_res + filename(image))
            return

        # Find blurriness value, if too high, move to blurry folder.
        val = cv2.Laplacian(img, cv2.CV_64F).var()
        if val < BLURRINESS_THRESHOLD:
            move(image, too_blurry + filename(image))
            return

        # Hash image.
        if hashing:
            hashes[image] = str(dhash(Image.open(image)))
Exemplo n.º 2
0
def get_gps(data_dir, some_gps, good_gps, bad_gps, location, METRES_THR=500):
    files = glob("{}*.jpg".format(data_dir), recursive=True)

    images_with_gps = {}
    nothing = []
    for image in tqdm(files):
        try:
            lat, lon, alt, bearing = get_exif_location(get_exif_data(image))
            if lat and lon:
                # Not really good but there seem to be a lot of images that just say 0m, have to filter.
                if alt and alt != 0:
                    images_with_gps[image] = {
                        "lat": lat,
                        "lon": lon,
                        "alt": alt,
                        "bearing": bearing
                    }
            else:
                nothing.append(image)
        except Exception as e:
            nothing.append((image, e))

    print("GPS FOUND FOR:", len(images_with_gps.keys()))
    print("NOT FOUND FOR:", len(nothing))

    incorrect_items, correct_items = {}, {}
    for image in images_with_gps.keys():
        distance = measure(images_with_gps[image]["lat"],
                           images_with_gps[image]["lon"], location.latitude,
                           location.longitude)
        if distance < METRES_THR:
            correct_items[image] = distance
        else:
            incorrect_items[image] = distance

    for item in incorrect_items.keys():
        move(item, bad_gps + filename(item))

    good_gps_to_save = {}
    some_gps_to_save = {}
    for item in correct_items.keys():
        fname = filename(item)
        # If image has bearing tag.
        if images_with_gps[item]["bearing"]:
            move(item, good_gps + fname)
            good_gps_to_save[fname] = images_with_gps[item]
        else:
            move(item, some_gps + fname)
            some_gps_to_save[fname] = images_with_gps[item]

    with open("intermediate/gps_data_from_images.json", "w") as outfile:
        json.dump(good_gps_to_save, outfile, indent=4)

    with open("intermediate/some_gps_data_from_images.json", "w") as outfile:
        json.dump(some_gps_to_save, outfile, indent=4)
Exemplo n.º 3
0
def remove_exif(some_gps, cleared_gps):
    images = glob(some_gps + "/*")
    # https://stackoverflow.com/questions/19786301/python-remove-exif-info-from-images
    for image in tqdm(images):
        try:
            photo = gpsphoto.GPSPhoto(image)
            photo.stripData(cleared_gps + filename(image))
        except:
            print(image + "- FALLBACK TO FULL CLEAR")
            img = Image.open(image)
            data = list(img.getdata())
            img_without_exif = Image.new(img.mode, img.size)
            img_without_exif.putdata(data)
            img_without_exif.save(cleared_gps + filename(image))
Exemplo n.º 4
0
def select_and_copy_GPS_images(data_dir, good_gps, NUM_GPS_IMAGES,
                               NUM_LARGEST_IMAGES, openMVG_images):
    # Load previous images used if the file exists.
    gps_images = []
    if os.path.isfile("logs/images_for_georeferencing.json"):
        with open("logs/images_for_georeferencing.json", "r") as infile:
            gps_images = json.load(infile)

    # Sort possible GPS images by size (maximise ability to be included) and set number to be
    # added to minus what is already there.
    possible_gps = sorted(glob(good_gps + "*.jpg"),
                          key=os.path.getsize,
                          reverse=True)

    # Add only enough images to fill the quota, not removing those there.
    # If there aren't enough, all will be used.
    for image in possible_gps:
        if len(gps_images) >= NUM_GPS_IMAGES:
            break
        if image not in gps_images:
            gps_images.append(image)

    # Save the images for later.
    with open("logs/images_for_georeferencing.json", "w+") as outfile:
        json.dump(gps_images, outfile, indent=4)

    # Move images to folder
    for image in gps_images:
        copy(image, openMVG_images + filename(image))

    # Sort by size and move the amount needed.
    sorted_by_size = sorted(glob(data_dir + "*.jpg"),
                            key=os.path.getsize,
                            reverse=True)

    images_used = []
    if os.path.isfile("logs/images_used.json"):
        with open("logs/images_used.json", "r") as infile:
            images_used = json.load(infile)

    for image in sorted_by_size:
        if len(images_used) >= NUM_LARGEST_IMAGES:
            break
        if image not in images_used:
            images_used.append(image)
            copy(image, openMVG_images + filename(image))

    with open("logs/images_used.json", "w+") as outfile:
        json.dump(images_used, outfile, indent=4)
Exemplo n.º 5
0
def export_gps_to_file(georeference, output="openMVG/"):
    with open(georeference) as f:
        data = json.load(f)

    key_to_fname = {
        view["value"]["ptr_wrapper"]["data"]["id_pose"]:
        view["value"]["ptr_wrapper"]["data"]["filename"]
        for view in data["views"]
    }

    fname_to_gps = {
        key_to_fname[ext["key"]]: ext["value"]["center"]
        for ext in data["extrinsics"]
    }

    recovered = {}
    for key in fname_to_gps.keys():
        x, y, z = fname_to_gps[key][0], fname_to_gps[key][1], fname_to_gps[
            key][2]
        lat, lon, alt = ecef2lla(x, y, z)
        recovered[key] = {"lat": lat[0][0], "lon": lon[0][0], "alt": alt[0][0]}
        #print(key_to_filename[key], lat[0][0], lon[0][0])

    no_ext = filename(georeference).split(".")[-2]
    with open(output + no_ext + "_positions.json", "w") as outfile:
        json.dump(recovered, outfile, indent=4)
def get_duplicate_images(path, duplicate, threshold=5):
    print("CALCULATING SIZE FOR EACH IMAGE FILE")
    sizes = {}
    images = glob(path + "*.jpg", recursive=True)
    for image in images:
        sizes[image] = Path(image).stat().st_size

    print("COMPUTING CLOSE IMAGES:")
    files = glob(path + "*.jpg", recursive=True)
    with open("logs/hashes.json", "r") as infile:
        hashes = json.load(infile)

    for key, hash in hashes.items():
        hashes[key] = hex_to_hash(hash)

    close = []
    from copy import deepcopy
    comparison = deepcopy(files)
    for image1 in tqdm(files):
        comparison = {
            path: hashes[path] - hashes[image1]
            for path in comparison if path != image1
        }
        for image2, result in comparison.items():
            if result <= threshold:
                try:
                    # Chose the one with the smaller size to be moved.
                    if sizes[image1] > sizes[image2]:
                        if image2 not in close:
                            close.append(image2)
                    else:
                        if image1 not in close:
                            close.append(image1)

                except FileNotFoundError:
                    # The offending file was likely moved in a previous pair
                    continue
        comparison.pop(image1, None)

    print("MOVING FOUND ITEMS TO 'duplicates' FOLDER")
    for image in close:
        move(image, duplicate + filename(image))

    return close
Exemplo n.º 7
0
def get_accuracy(gps_data,
                 sfm_geo_positions,
                 sfm_expanded_positions,
                 output=None,
                 georeferencing="logs/images_for_georeferencing.json"):
    # Ground truth
    with open(gps_data, "r") as infile:
        actual = json.load(infile)

    # Position after localisation
    with open(sfm_expanded_positions, "r") as infile:
        localised = json.load(infile)

    # Getting difference to check which images were newly localised.
    with open(sfm_geo_positions, "r") as infile:
        geo_positions = json.load(infile)
    localised_images = [
        img for img in localised.keys() if img not in geo_positions.keys()
    ]

    with open(georeferencing, "r") as infile:
        used_for_georeferencing = json.load(infile)
    used_for_georeferencing = [
        filename(img) for img in used_for_georeferencing
    ]

    newly_localised = {}
    sum_error = 0
    for key in localised.keys():
        # Image not used for georeferencing but as the only images used for localisation were those with GPS cleared... The image has accurate GPS.
        if key in actual.keys(
        ) and key in localised_images and key not in used_for_georeferencing:
            lat1, lat2 = localised[key]["lat"], actual[key]["lat"]
            lon1, lon2 = localised[key]["lon"], actual[key]["lon"]
            lat_distance = lat1 - lat2
            lon_distance = lon1 - lon2

            # Only do altitude for images that have them
            if "alt" in localised[key]:
                alt1, alt2 = localised[key]["alt"], actual[key]["alt"]
                alt_distance = alt1 - alt2

            metres_distance = measure(lat1, lon1, lat2, lon2)
            sum_error += metres_distance
            newly_localised[key] = {
                "actual": {
                    "lat": lat2,
                    "lon": lon2
                },
                "localised": {
                    "lat": lat1,
                    "lon": lon1
                },
                "change_in_coords": {
                    "lat_change": lat_distance,
                    "lon_change": lon_distance
                },
                "metres_distance_from_actual": metres_distance
            }
            if "alt" in localised[key]:
                newly_localised[key]["actual"]["alt"] = alt2
                newly_localised[key]["localised"]["alt"] = alt1
                newly_localised[key]["change_in_coords"][
                    "alt_change"] = alt_distance

    newly_localised["sum_error"] = sum_error

    if output:
        json.dump(newly_localised, open(output, "w+"), indent=4)
def merge_reconstructions(a=None, b=None):
    reconstructions = glob("reconstructions/*")
    options = list(combinations(reconstructions, 2))

    if not a or not b:
        option = None
        if options:
            while option not in range(-1, len(options)):
                for num, option in enumerate(options):
                    short = (option[0].replace("reconstructions/", ""),
                             option[1].replace("reconstructions/", ""))
                    print(num, "-", short)
                print("-1 - EXIT DIALOG")
                try:
                    option = int(input())
                except:
                    option = None

        if option == -1:
            return

        a, b = options[option][0], options[option][1]

    # Conveniences
    merge_name = filename(a) + "~" + filename(b)
    merge_name = merge_name.replace(" ", "_")

    # Create folders for merging.
    create_folder("reconstructions/" + merge_name)
    create_folder("reconstructions/" + merge_name + "/openMVG/")
    create_folder("reconstructions/" + merge_name + "/openMVG/" + "data/")
    create_folder("reconstructions/" + merge_name + "/openMVG/" +
                  "localization_images/")
    create_folder("reconstructions/" + merge_name + "/openMVG/" +
                  "some_gps_localization/")
    create_folder("reconstructions/" + merge_name + "/openMVG/" + "output/")
    create_folder("reconstructions/" + merge_name + "/intermediate/")
    create_folder("reconstructions/" + merge_name + "/logs/")

    # Copy features and descriptors for one part of the pair
    features, descriptors = glob(a + "/openMVG/data/*.feat"), glob(
        a + "/openMVG/data/*.desc")

    for feature, descriptor in zip(features, descriptors):
        filename1 = filename(feature)
        filename2 = filename(descriptor)
        copy(feature,
             "reconstructions/" + merge_name + "/openMVG/data/" + filename1)
        copy(descriptor,
             "reconstructions/" + merge_name + "/openMVG/data/" + filename2)

    # Copy features and descriptors for the second part of the pair
    features, descriptors = glob(b + "/openMVG/data/*.feat"), glob(
        b + "/openMVG/data/*.desc")

    for feature, descriptor in zip(features, descriptors):
        filename1 = filename(feature)
        filename2 = filename(descriptor)
        copy(feature,
             "reconstructions/" + merge_name + "/openMVG/data/" + filename1)
        copy(descriptor,
             "reconstructions/" + merge_name + "/openMVG/data/" + filename2)

    copy(
        a + "/openMVG/data/image_describer.json",
        "reconstructions/" + merge_name + "/openMVG/data/image_describer.json")

    # Copy over the localisation images from both reconstructions.
    localisation_one = glob(a + "/openMVG/localization_images/*")
    localisation_two = glob(b + "/openMVG/localization_images/*")

    for img in localisation_one:
        copy(
            img, "reconstructions/" + merge_name +
            "/openMVG/localization_images/" + filename(img))

    for img in localisation_two:
        copy(
            img, "reconstructions/" + merge_name +
            "/openMVG/localization_images/" + filename(img))

    some_gps_one = glob(a + "/openMVG/some_gps_localization/*")
    some_gps_two = glob(b + "/openMVG/some_gps_localization/*")

    for img in some_gps_one:
        copy(
            img, "reconstructions/" + merge_name +
            "/openMVG/some_gps_localization/" + filename(img))

    for img in some_gps_two:
        copy(
            img, "reconstructions/" + merge_name +
            "/openMVG/some_gps_localization/" + filename(img))

    with open(a + "/intermediate/gps_data_from_images.json", "r") as infile:
        gps1 = json.load(infile)

    with open(b + "/intermediate/gps_data_from_images.json", "r") as infile:
        gps2 = json.load(infile)

    merged_gps = {}
    for key, val in gps1.items():
        merged_gps[key] = val
    for key, val in gps2.items():
        merged_gps[key] = val

    with open(
            "reconstructions/" + merge_name +
            "/intermediate/gps_data_from_images.json", "w+") as outfile:
        json.dump(merged_gps, outfile, indent=4)

    with open(a + "/intermediate/some_gps_data_from_images.json",
              "r") as infile:
        gps1 = json.load(infile)

    with open(b + "/intermediate/some_gps_data_from_images.json",
              "r") as infile:
        gps2 = json.load(infile)

    merged_gps = {}
    for key, val in gps1.items():
        merged_gps[key] = val
    for key, val in gps2.items():
        merged_gps[key] = val

    with open(
            "reconstructions/" + merge_name +
            "/intermediate/some_gps_data_from_images.json", "w+") as outfile:
        json.dump(merged_gps, outfile, indent=4)

    # Merge the actual "sfm_data".
    from sfm_data import merge_sfm_data
    merge_sfm_data(
        a + "/openMVG/output/sfm_data_geo.json",
        b + "/openMVG/output/sfm_data_geo.json",
        "reconstructions/" + merge_name + "/openMVG/output/sfm_data_geo.json")

    # Localise images in reconstruction and make relevant files.
    commands = [
        """
        openMVG_main_ConvertSfM_DataFormat \
            -i reconstructions/{}/openMVG/output/sfm_data_geo.json \
            -o reconstructions/{}/openMVG/output/sfm_data_geo.bin \
    """.format(merge_name, merge_name), """
        openMVG_main_ConvertSfM_DataFormat \
            -i reconstructions/{}/openMVG/output/sfm_data_geo.bin \
            -o reconstructions/{}/openMVG/output/sfm_data_geo.ply \
    """.format(merge_name, merge_name), """
    openMVG_main_SfM_Localization \
        -i reconstructions/{}/openMVG/output/sfm_data_geo.bin \
        --match_dir reconstructions/{}/openMVG/data \
        --out_dir reconstructions/{}/openMVG/localization_output \
        --query_image_dir reconstructions/{}/openMVG/localization_images \
        --numThreads {}
    """.format(merge_name, merge_name, merge_name, merge_name, cpu_count()),
        """
    openMVG_main_SfM_Localization \
        -i reconstructions/{}/openMVG/output/sfm_data_geo.bin \
        --match_dir reconstructions/{}/openMVG/data \
        --out_dir reconstructions/{}/openMVG/some_gps_localization_output \
        --query_image_dir reconstructions/{}/openMVG/some_gps_localization/ \
        --numThreads {}
    """.format(merge_name, merge_name, merge_name, merge_name, cpu_count())
    ]
    for cmd in commands:
        os.system(cmd)

    from gps import export_gps_to_file
    export_gps_to_file(georeference="reconstructions/" + merge_name +
                       "/openMVG/output/sfm_data_geo.json",
                       output="reconstructions/" + merge_name + "/openMVG/")
    export_gps_to_file(georeference="reconstructions/" + merge_name +
                       "/openMVG/localization_output/sfm_data_expanded.json",
                       output="reconstructions/" + merge_name + "/openMVG/")
    export_gps_to_file(
        georeference="reconstructions/" + merge_name +
        "/openMVG/some_gps_localization_output/sfm_data_expanded.json",
        output="reconstructions/" + merge_name +
        "/openMVG/some_gps_localization_output/")

    with open(a + "/logs/images_for_georeferencing.json", "r") as infile:
        used_for_geo1 = json.load(infile)

    with open(b + "/logs/images_for_georeferencing.json", "r") as infile:
        used_for_geo2 = json.load(infile)

    with open(
            "reconstructions/" + merge_name +
            "/logs/images_for_georeferencing.json", "w+") as outfile:
        merged_used_for_geo = used_for_geo1 + used_for_geo2
        json.dump(merged_used_for_geo, outfile, indent=4)

    from gps import get_accuracy
    get_accuracy("reconstructions/" + merge_name +
                 "/intermediate/gps_data_from_images.json",
                 "reconstructions/" + merge_name +
                 "/openMVG/sfm_data_geo_positions.json",
                 "reconstructions/" + merge_name +
                 "/openMVG/sfm_data_expanded_positions.json",
                 output="reconstructions/" + merge_name +
                 "/openMVG/localised_accuracy.json",
                 georeferencing="reconstructions/" + merge_name +
                 "/logs/images_for_georeferencing.json")

    get_accuracy(
        "reconstructions/" + merge_name +
        "/intermediate/some_gps_data_from_images.json",
        "reconstructions/" + merge_name +
        "/openMVG/sfm_data_geo_positions.json",
        "reconstructions/" + merge_name +
        "/openMVG/some_gps_localization_output/sfm_data_expanded_positions.json",
        output="reconstructions/" + merge_name +
        "/openMVG/some_gps_localised_accuracy.json",
        georeferencing="reconstructions/" + merge_name +
        "/logs/images_for_georeferencing.json")

    from gps import convert_to_kml
    convert_to_kml(georeference="reconstructions/" + merge_name +
                   "/openMVG/sfm_data_expanded_positions.json",
                   output="reconstructions/" + merge_name +
                   "/openMVG/positions.kml")

    # Compare accuracy of localisation between reconstructions.
    acc1 = a + "/openMVG/localised_accuracy.json"
    acc2 = b + "/openMVG/localised_accuracy.json"
    acc1 = json.load(open(acc1, "r"))
    acc2 = json.load(open(acc2, "r"))
    new_acc = json.load(
        open(
            "reconstructions/" + merge_name +
            "/openMVG/localised_accuracy.json", "r"))
    acc_changes = {}
    for img in new_acc.keys():
        difference_accuracy = None
        if img != "sum_error":
            if img in acc1.keys():
                difference_accuracy = acc1[img]["metres_distance_from_actual"] - \
                    new_acc[img]["metres_distance_from_actual"]
            if img in acc2.keys():
                difference_accuracy = acc2[img]["metres_distance_from_actual"] - \
                    new_acc[img]["metres_distance_from_actual"]
            if difference_accuracy:
                acc_changes[img] = difference_accuracy

    acc_changes["sum"] = sum(acc_changes.values())

    json.dump(acc_changes,
              open(
                  "reconstructions/" + merge_name +
                  "/accuracy_changes_from_merge.json", "w+"),
              indent=4)
Exemplo n.º 9
0
def handle_choice(choice):
    if choice == 1:
        from download import links_from_flickr, download
        links = links_from_flickr(TOPIC)
        download(links, "intermediate/images/")

    elif choice == 2:
        from images import images_rename
        images_rename("intermediate/images/")

        commands = [
            # Convert PNGs to JPGs.
            """mogrify -format jpg {}*.png;""".format("intermediate/images/"),

            # Remove PNG duplicates
            """rm {}/*.png;""".format("intermediate/images/"),

            # Check for faulty JPGs, if so, remove.
            """jpeginfo -cd {}*.jpg;""".format("intermediate/images/")
        ]
        for cmd in commands:
            os.system(cmd)

    elif choice == 3:
        from images import check_images, get_duplicate_images
        check_images("intermediate/images/",
                     "intermediate/too_small/",
                     "intermediate/too_blurry/",
                     RESOLUTION_THRESHOLD=PIXEL_NUM_THRESHOLD,
                     BLURRINESS_THRESHOLD=BLURRINESS_THRESHOLD)

        close_images = get_duplicate_images("intermediate/images/",
                                            "intermediate/duplicates/",
                                            threshold=CLOSE_IMAGE_THRESHOLD)
        print("IMAGES CLOSE BY HASH:")
        pprint(close_images)

    elif choice == 4:
        from gps import get_gps
        get_gps("intermediate/images/",
                "intermediate/some_gps/",
                "intermediate/good_gps/",
                "intermediate/bad_gps/",
                location,
                METRES_THR=METRES_RADIUS_THRESHOLD)
        from gps import remove_exif
        remove_exif("intermediate/good_gps/", "intermediate/cleared_gps/")
        remove_exif("intermediate/some_gps/", "intermediate/cleared_some_gps/")

    elif choice == 5:
        from gps import select_and_copy_GPS_images
        select_and_copy_GPS_images("intermediate/images/",
                                   "intermediate/good_gps/", NUM_GPS_IMAGES,
                                   NUM_LARGEST_IMAGES, "openMVG/images/")

        localization_images = glob("intermediate/good_gps/*.jpg")
        some_gps_images = glob("intermediate/some_gps/*.jpg")

        with open("logs/images_for_georeferencing.json", "r") as infile:
            used_for_georeferencing = json.load(infile)

        from fileio import copy
        not_used_for_georeferencing = []
        for image in localization_images:
            if image not in used_for_georeferencing:
                copy("intermediate/cleared_gps/" + filename(image),
                     "openMVG/localization_images/" + filename(image))
                not_used_for_georeferencing.append(image)

        for image in some_gps_images:
            copy("intermediate/cleared_some_gps/" + filename(image),
                 "openMVG/some_gps_localization/" + filename(image))

        with open("logs/not_used_for_georeferencing.json", "w+") as outfile:
            json.dump(not_used_for_georeferencing, outfile, indent=4)

    elif choice == 6:
        commands = [
            """
			openMVG_main_SfMInit_ImageListing \
				-i openMVG/images \
				-d sensor_database.txt \
				-o openMVG/init \
                | tee logs/image_listing.txt
			""", """
			openMVG_main_ComputeFeatures \
				-i openMVG/init/sfm_data.json \
				-o openMVG/data \
				--describerMethod SIFT \
				--describerPreset {} \
                --numThreads {}
			""".format(DESCRIBER_PRESET, cpu_count()), """
			openMVG_main_ComputeMatches \
				-i openMVG/init/sfm_data.json \
				-o openMVG/data/ \
                --guided_matching 1 \
                --force 1 \
                | tee logs/matching.txt
			"""
        ]
        for cmd in commands:
            os.system(cmd)

    elif choice == 7:
        cmd = \
        """
        openMVG_main_IncrementalSfM \
            -i openMVG/init/sfm_data.json \
            -m openMVG/data \
            -o openMVG/output \
            --prior_usage 0
        """

        os.system(cmd)

    elif choice == 8:
        #from sfm_data import remove_images_from_reconstruction
        cmd = \
        """
        openMVG_main_ConvertSfM_DataFormat \
            -i openMVG/output/sfm_data.bin \
            -o openMVG/output/sfm_data.json
        """

        os.system(cmd)

        LMeds_usage = ""
        while LMeds_usage not in ["y", "n"]:
            LMeds_usage = input(
                "Use of the OpenMVG LMeds model for georegistration [y/n]? ")

        if LMeds_usage == "y":
            LMeds_usage = "0"
        else:
            LMeds_usage = "1"

        commands = [
            """
            openMVG_main_ConvertSfM_DataFormat \
				-i openMVG/output/sfm_data.json \
				-o openMVG/output/sfm_data_modified.bin
            """, """
            openMVG_main_geodesy_registration_to_gps_position \
				-i openMVG/output/sfm_data_modified.bin \
				-o openMVG/output/sfm_data_geo.bin \
                -m {} \
                | tee logs/georegistration.txt
            """.format(LMeds_usage), """
            openMVG_main_ConvertSfM_DataFormat \
				-i openMVG/output/sfm_data_geo.bin \
				-o openMVG/output/sfm_data_geo.json
            """, """
            openMVG_main_ConvertSfM_DataFormat \
				-i openMVG/output/sfm_data_geo.bin \
				-o openMVG/output/sfm_data_geo_cloudcompare_viewable.ply
            """
        ]
        for cmd in commands:
            os.system(cmd)

    elif choice == 9:
        commands = [
            """
		openMVG_main_SfM_Localization \
			-i openMVG/output/sfm_data_geo.bin \
			--match_dir openMVG/data \
			--out_dir openMVG/localization_output/ \
			--query_image_dir openMVG/localization_images/ \
			--numThreads {}
		""".format(cpu_count()), """
		openMVG_main_SfM_Localization \
			-i openMVG/output/sfm_data_geo.bin \
			--match_dir openMVG/data \
			--out_dir openMVG/some_gps_localization_output/ \
			--query_image_dir openMVG/some_gps_localization/ \
			--numThreads {}
		""".format(cpu_count())
        ]

        for cmd in commands:
            os.system(cmd)

        from gps import export_gps_to_file, get_accuracy, convert_to_kml

        export_gps_to_file(georeference="openMVG/output/sfm_data_geo.json")

        # Accurate GPS images
        export_gps_to_file(
            georeference="openMVG/localization_output/sfm_data_expanded.json")
        get_accuracy("intermediate/gps_data_from_images.json",
                     "openMVG/sfm_data_geo_positions.json",
                     "openMVG/sfm_data_expanded_positions.json",
                     output="openMVG/localised_accuracy.json")

        convert_to_kml(georeference="openMVG/sfm_data_expanded_positions.json",
                       gps_data="openMVG/localised_accuracy.json")

        # Somewhat accurate GPS images
        export_gps_to_file(
            georeference=
            "openMVG/some_gps_localization_output/sfm_data_expanded.json",
            output="openMVG/some_gps_localization_output/")

        get_accuracy(
            "intermediate/some_gps_data_from_images.json",
            "openMVG/sfm_data_geo_positions.json",
            "openMVG/some_gps_localization_output/sfm_data_expanded_positions.json",
            output="openMVG/some_gps_localised_accuracy.json")

        convert_to_kml(
            georeference=
            "openMVG/some_gps_localization_output/sfm_data_expanded_positions.json",
            output="openMVG/some_gps_positions.kml",
            gps_data="openMVG/some_gps_localised_accuracy.json")

    elif choice == 10:
        from fileio import move, copy
        create_folder("reconstructions/" + GEO_TOPIC)
        move("openMVG", "reconstructions/" + GEO_TOPIC + "/")
        move("intermediate", "reconstructions/" + GEO_TOPIC + "/")
        move("logs", "reconstructions/" + GEO_TOPIC + "/")
        copy("./config.py", "reconstructions/" + GEO_TOPIC + "/config.py")

    elif choice == 11:
        from sfm_data import merge_reconstructions
        merge_reconstructions()

    elif choice == -1:
        exit(0)