kopia lustrzana https://github.com/OpenDroneMap/ODM
minor refactor for readability, add credits + README
rodzic
e84c77dd56
commit
820ea4a4e3
|
@ -0,0 +1,26 @@
|
||||||
|
# exif_binner.py
|
||||||
|
|
||||||
|
Bins multispectral drone images by spectral band, using EXIF data. Also verifies that each bin is complete (i.e. contains all expected bands) and can log errors to a CSV file. Excludes RGB images by default.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [Pillow](https://pillow.readthedocs.io/en/stable/installation.html) library for reading images and EXIF data.
|
||||||
|
- [tqdm](https://github.com/tqdm/tqdm#installation) for progress bars - can be removed
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
exif_binner.py <args> <path to folder of images to rename> <output folder>
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional arguments:
|
||||||
|
|
||||||
|
- `-b`/`--bands <integer>`: Number of expected bands per capture. Default: `5`
|
||||||
|
- `-s`/`--sequential <True/False>`: Use sequential capture group in filenames rather than original capture ID. Default: `True`
|
||||||
|
- `-z`/`--zero_pad <integer>`: If using sequential capture groups, zero-pad the group number to this many digits. 0 for no padding, -1 for auto padding. Default: `5`
|
||||||
|
- `-w`/`--whitespace_replace <string>`: Replace whitespace characters with this character. Default: `-`
|
||||||
|
- `-l`/`--logfile <filename>`: Write processed image metadata to this CSV file
|
||||||
|
- `-r`/`--replace_filename <string>`: Use this instead of using the original filename in new filenames.
|
||||||
|
- `-f`/`--force`: Do not ask for processing confirmation.
|
||||||
|
- `-g`/`--no_grouping`: Do not apply grouping, only validate and add band name.
|
||||||
|
- Show these on the command line with `-h`/`--help`.
|
|
@ -1,23 +1,25 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Originally developed by Ming Chia at the Australian Plant Phenomics Facility (Australian National University node)
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
# exif_binner.py <args> <path to folder of images to rename> <output folder>
|
||||||
|
|
||||||
# standard libraries
|
# standard libraries
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
import PIL
|
|
||||||
from PIL import Image, ExifTags
|
|
||||||
import shutil
|
import shutil
|
||||||
from tqdm import tqdm
|
|
||||||
import re
|
import re
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import argparse
|
import argparse
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
|
|
||||||
# Usage:
|
# other imports
|
||||||
# python exif_binner.py <args> <path to folder of images to rename> <output folder>
|
import PIL
|
||||||
|
from PIL import Image, ExifTags
|
||||||
|
from tqdm import tqdm # optional: see "swap with this for no tqdm" below
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
# required args
|
# required args
|
||||||
parser.add_argument("file_dir", help="input folder of images")
|
parser.add_argument("file_dir", help="input folder of images")
|
||||||
|
@ -77,9 +79,8 @@ images = []
|
||||||
|
|
||||||
print("Indexing images ...")
|
print("Indexing images ...")
|
||||||
|
|
||||||
# Uses tqdm() for the progress bar, if not needed swap with
|
|
||||||
# for filename in os.listdir(file_dir):
|
|
||||||
|
|
||||||
|
# for filename in os.listdir(file_dir): # swap with this for no tqdm
|
||||||
for filename in tqdm(os.listdir(file_dir)):
|
for filename in tqdm(os.listdir(file_dir)):
|
||||||
old_path = os.path.join(file_dir, filename)
|
old_path = os.path.join(file_dir, filename)
|
||||||
file_name, file_ext = os.path.splitext(filename)
|
file_name, file_ext = os.path.splitext(filename)
|
||||||
|
@ -143,6 +144,7 @@ images = sorted(images, key=lambda img: (img["DateTime"], img["name"]))
|
||||||
|
|
||||||
# now sort and identify valid entries
|
# now sort and identify valid entries
|
||||||
if not args.no_grouping:
|
if not args.no_grouping:
|
||||||
|
# for this_img in images: # swap with this for no tqdm
|
||||||
for this_img in tqdm(images):
|
for this_img in tqdm(images):
|
||||||
if not this_img["valid"]: # prefiltered in last loop
|
if not this_img["valid"]: # prefiltered in last loop
|
||||||
continue
|
continue
|
||||||
|
@ -166,6 +168,7 @@ os.makedirs(output_invalid, exist_ok=True)
|
||||||
identifier = ""
|
identifier = ""
|
||||||
|
|
||||||
# then do the actual copy
|
# then do the actual copy
|
||||||
|
# for this_img in images: # swap with this for no tqdm
|
||||||
for this_img in tqdm(images):
|
for this_img in tqdm(images):
|
||||||
old_path = os.path.join(file_dir, this_img["name"])
|
old_path = os.path.join(file_dir, this_img["name"])
|
||||||
file_name, file_ext = os.path.splitext(this_img["name"])
|
file_name, file_ext = os.path.splitext(this_img["name"])
|
||||||
|
|
Ładowanie…
Reference in New Issue