sitka.land

how-to

Map Imagery

Intro

This covers how to process and publish the photos. This does not cover how to take the photos. Also, covered is how to update the 'flights' page that uses geojson points to embed images.

Click these for more info .

Step 1. Organize

The first step is to get all the images into one folder with sequential filenames.

Group images into folders by the 1000s. Once DJI drones reach filename DJI_0999.JPG, they start back at DJI_0001.JPG. So, group them into folders named the following:

  • πŸ“ 100
  • πŸ“ 1000
  • πŸ“ 2000
  • πŸ“ 3000

In terminal, navigate to the root of the images folder and run the following python script.

DJI_0001.JPG ➑️ DJI_1001.JPG
import os
import shutil

# Work from current directory
root_dir = "."

# Folders to rename and move from
groups = ["100", "1000", "2000", "3000"]

# Step 1: Rename files (skip 100)
for group in groups:
	if group == "100":
		continue  # skip renaming for folder 100

	group_path = os.path.join(root_dir, group)

	# List and sort image files
	files = sorted([
		f for f in os.listdir(group_path)
		if f.lower().endswith(('.jpg', '.jpeg'))
	])

	for filename in files:
		base, ext = os.path.splitext(filename)
		num_str = base.split("_")[-1]
		try:
			num = int(num_str)
		except ValueError:
			print(f"Skipping {filename}: could not parse number")
			continue

		new_num = int(group) + num
		new_filename = f"DJI_{new_num:04d}{ext}"

		src = os.path.join(group_path, filename)
		dst = os.path.join(group_path, new_filename)
		os.rename(src, dst)
		print(f"Renamed {src} -> {dst}")

# Step 2: Move all files from each group into root_dir
for group in groups:
	group_path = os.path.join(root_dir, group)

	files = [
		f for f in os.listdir(group_path)
		if f.lower().endswith(('.jpg', '.jpeg')) and os.path.isfile(os.path.join(group_path, f))
	]

	for f in files:
		src = os.path.join(group_path, f)
		dst = os.path.join(root_dir, f)

		# Prevent overwriting by prefixing on conflict
		if os.path.exists(dst):
			dst = os.path.join(root_dir, f"{group}_{f}")

		shutil.move(src, dst)
		print(f"Moved {src} -> {dst}")

Step 2. Process

Now the photos are ready to be processed. I like to use OpenDroneMap in the command line interface which is easy on MacOS through Docker. Make sure the folder structure is like this:

  • πŸ“‚ Documents
    • πŸ“‚ odm
      • πŸ“‚ datasets
        • πŸ“‚ project
          • πŸ“ images

Then run this command in terminal

docker run -ti --rm -v ~/Documents/odm/datasets:/datasets opendronemap/odm --project-path /datasets project --orthophoto-resolution 2.0

Step 3. Georeference

The "out-of-the-box" orthophoto is fine for some purposes. For consistency, I'm using lidar to align my ortho-imagery after it's processed into an orthophoto. Rather than the painstakingly difficult process of setting up in the real-world, I georeference the out-of-the-box orthophoto to a Web Mercator map with building footprints that were drawn over lidar features.

First I like to open the odm_orthophoto.original.tif in Gimp and trim nice rounded edges and also excise areas that were covered better in other datasets.

Step 4. Generate XYZ Tiles

There are some settings that I do from memory that I should write down for once.

  • Minimum Zoom: 12
  • Maximum Zoom: 21
  • DPI: 192
  • Tile Size (width and height): 512

Step 5. Upload and Merge

I've just updated the Jarvis area and am uploading the folders now. Once that's completed I'll put the 'jarvis' folder next to the 'imagery' folder and run this command:

rsync -av --progress jarvis/ imagery/

Or run in background and log results (better for really big merges):

nohup rsync -av --progress jarvis/ imagery/ > rsync.log 2>&1 &

Another handy command is to unzip through terminal and not worry about getting disconnected

nohup unzip 12.zip > unzip.log 2>&1 &

You can watch as the unzip.log is written to with

tail -f unzip.log

Side Quest 1. Flights Page

It's fun to update the flights page. I use the 'Import Photos' plugin in QGIS to create a points layer of all the photos that were just organized. From here I would like to simply save the points layer as a Geojson but the points do not get exported in the same order the pictures were taken. The following process works well for sorting them in order:

  • Export as .csv containing only 3 columns: X, Y, Name
  • Open in spreadsheet app
  • Sort the Name column
  • Add a sequential column and fill
  • Save as .csv
  • Import into QGIS and then export as .geojson with a coordinate precision of 6
  • Open the geojson in a text editor, add "dir" and appropriate number. Concatenate to points.geojson on the server.

Side Quest 2. Photo Prep

After organizing the photos I like to import them with their new filenames into the Photos app. From there we can export the photos to various sizes. The following is my image size convention for 4:3 photos

  • th: 120 x 90
  • xs: 240 x 180
  • sm: 480 x 360
  • md: 960 x 720
  • lg: 1920 x 1440
  • xl: 3840 x 2880
  • og: 5280 x 3956

Photos exports filenames as 'jpeg' and I prefer to rename all the files to 'jpg'. The following script works to fix that.

import os
	
# Walk through all subdirectories and files
for root, dirs, files in os.walk("."):
	for filename in files:
		if filename.lower().endswith(".jpeg"):
			old_path = os.path.join(root, filename)
			new_filename = filename[:-5] + ".jpg"
			new_path = os.path.join(root, new_filename)
			try:
				os.rename(old_path, new_path)
				print(f"Renamed '{old_path}' to '{new_path}'")
			except Exception as e:
				print(f"Error renaming '{old_path}': {e}")

Currently, I only have plans to use sizes xs, md, and lg. I'm uploading those into the 'img' folder which is then subdivided in 'dir' by flight number.

Eventually, I will get the original (og) photos uploaded and be able to delete them from the laptop.

After zipping and uploading photos sometimes there are extra files added and permissions that get messed up. Use this command in terminal on the server to remove extra files created by MacOS.

find . \( -name '._*' -o -name '.DS_Store' \) -type f -delete

Use these commands to change permissions of the directories and the images that were unzipped.

find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;