Skip to content

Commit 94af3b9

Browse files
authored
Merge pull request #72 from sbonaime/master
fix for reading gcp_file.txt
2 parents 0435df6 + 180e05a commit 94af3b9

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed

dm/opendm/gcp.py

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@ def __init__(self, gcp_path):
1515
def read(self):
1616
if self.exists():
1717
with open(self.gcp_path, 'r') as f:
18-
contents = f.read().decode('utf-8-sig').encode('utf-8').strip()
18+
contents = f.read().strip()
1919

20-
lines = map(str.strip, contents.split('\n'))
20+
# Strip eventual BOM characters
21+
contents = contents.replace('\ufeff', '')
22+
23+
lines = list(map(str.strip, contents.split('\n')))
2124
if lines:
2225
self.raw_srs = lines[0] # SRS
2326
self.srs = location.parse_srs_header(self.raw_srs)
2427

25-
for line in lines[1:]:
28+
for line in contents[1:]:
2629
if line != "" and line[0] != "#":
27-
parts = line.split()
30+
parts = line.strip().split()
2831
if len(parts) >= 6:
2932
self.entries.append(line)
3033
else:
@@ -34,6 +37,35 @@ def iter_entries(self):
3437
for entry in self.entries:
3538
yield self.parse_entry(entry)
3639

40+
def check_entries(self):
41+
coords = {}
42+
gcps = {}
43+
errors = 0
44+
45+
for entry in self.iter_entries():
46+
k = entry.coords_key()
47+
coords[k] = coords.get(k, 0) + 1
48+
if k not in gcps:
49+
gcps[k] = []
50+
gcps[k].append(entry)
51+
52+
for k in coords:
53+
if coords[k] < 3:
54+
description = "insufficient" if coords[k] < 2 else "not ideal"
55+
for entry in gcps[k]:
56+
log.ODM_WARNING(str(entry))
57+
log.ODM_WARNING("The number of images where the GCP %s has been tagged are %s" % (k, description))
58+
log.ODM_WARNING("You should tag at least %s more images" % (3 - coords[k]))
59+
log.ODM_WARNING("=====================================")
60+
errors += 1
61+
if len(coords) < 3:
62+
log.ODM_WARNING("Low number of GCPs detected (%s). For best results use at least 5." % (3 - len(coords)))
63+
log.ODM_WARNING("=====================================")
64+
errors += 1
65+
66+
if errors > 0:
67+
log.ODM_WARNING("Some issues detected with GCPs (but we're going to process this anyway)")
68+
3769
def parse_entry(self, entry):
3870
if entry:
3971
parts = entry.split()
@@ -51,6 +83,25 @@ def entries_count(self):
5183
def exists(self):
5284
return bool(self.gcp_path and os.path.exists(self.gcp_path))
5385

86+
def make_resized_copy(self, gcp_file_output, ratio):
87+
"""
88+
Creates a new resized GCP file from an existing GCP file. If one already exists, it will be removed.
89+
:param gcp_file_output output path of new GCP file
90+
:param ratio scale GCP coordinates by this value
91+
:return path to new GCP file
92+
"""
93+
output = [self.raw_srs]
94+
95+
for entry in self.iter_entries():
96+
entry.px *= ratio
97+
entry.py *= ratio
98+
output.append(str(entry))
99+
100+
with open(gcp_file_output, 'w') as f:
101+
f.write('\n'.join(output) + '\n')
102+
103+
return gcp_file_output
104+
54105
def wgs84_utm_zone(self):
55106
"""
56107
Finds the UTM zone where the first point of the GCP falls into

dm/opendm/location.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
def extract_utm_coords(photos, images_path, output_coords_file):
77
"""
8-
Create a coordinate file containing the GPS positions of all cameras
8+
Create a coordinate file containing the GPS positions of all cameras
99
to be used later in the ODM toolchain for automatic georeferecing
1010
:param photos ([ODM_Photo]) list of photos
1111
:param images_path (str) path to dataset images
@@ -14,7 +14,7 @@ def extract_utm_coords(photos, images_path, output_coords_file):
1414
"""
1515
if len(photos) == 0:
1616
raise Exception("No input images, cannot create coordinates file of GPS positions")
17-
17+
1818
utm_zone = None
1919
hemisphere = None
2020
coords = []
@@ -23,20 +23,20 @@ def extract_utm_coords(photos, images_path, output_coords_file):
2323
if photo.latitude is None or photo.longitude is None or photo.altitude is None:
2424
log.MM_ERROR("Failed parsing GPS position for %s, skipping" % photo.filename)
2525
continue
26-
26+
2727
if utm_zone is None:
2828
utm_zone, hemisphere = get_utm_zone_and_hemisphere_from(photo.longitude, photo.latitude)
2929

3030
try:
3131
coord = convert_to_utm(photo.longitude, photo.latitude, photo.altitude, utm_zone, hemisphere)
3232
except:
3333
raise Exception("Failed to convert GPS position to UTM for %s" % photo.filename)
34-
34+
3535
coords.append(coord)
3636

3737
if utm_zone is None:
3838
raise Exception("No images seem to have GPS information")
39-
39+
4040
# Calculate average
4141
dx = 0.0
4242
dy = 0.0
@@ -54,7 +54,7 @@ def extract_utm_coords(photos, images_path, output_coords_file):
5454
f.write("%s %s\n" % (dx, dy))
5555
for coord in coords:
5656
f.write("%s %s %s\n" % (coord[0] - dx, coord[1] - dy, coord[2]))
57-
57+
5858
def transform2(from_srs, to_srs, x, y):
5959
return transformer(from_srs, to_srs).TransformPoint(x, y, 0)[:2]
6060

@@ -73,14 +73,14 @@ def proj_srs_convert(srs):
7373
else:
7474
proj4 = srs.to_proj4()
7575
res.ImportFromProj4(proj4)
76-
76+
7777
return res
7878

7979
def transformer(from_srs, to_srs):
8080
src = proj_srs_convert(from_srs)
8181
tgt = proj_srs_convert(to_srs)
8282
return osr.CoordinateTransformation(src, tgt)
83-
83+
8484
def get_utm_zone_and_hemisphere_from(lon, lat):
8585
"""
8686
Calculate the UTM zone and hemisphere that a longitude/latitude pair falls on
@@ -106,7 +106,7 @@ def convert_to_utm(lon, lat, alt, utm_zone, hemisphere):
106106
p = Proj(proj='utm',zone=utm_zone,ellps='WGS84', preserve_units=True)
107107
else:
108108
p = Proj(proj='utm',zone=utm_zone,ellps='WGS84', preserve_units=True, south=True)
109-
109+
110110
x,y = p(lon, lat)
111111
return [x, y, alt]
112112

@@ -116,17 +116,17 @@ def parse_srs_header(header):
116116
:param header (str) line
117117
:return Proj object
118118
"""
119-
log.MM_INFO('Parsing SRS header: %s' % header)
119+
log.MM_INFO(f'Parsing spatial reference system (SRS) header: {header}')
120120
header = header.strip()
121121
ref = header.split(' ')
122122
try:
123123
if ref[0] == 'WGS84' and ref[1] == 'UTM':
124124
datum = ref[0]
125125
utm_pole = (ref[2][len(ref[2]) - 1]).upper()
126-
utm_zone = int(ref[2][:len(ref[2]) - 1])
127-
126+
utm_zone = int(ref[2][:-1])
127+
128128
proj_args = {
129-
'zone': utm_zone,
129+
'zone': utm_zone,
130130
'datum': datum
131131
}
132132

@@ -140,7 +140,7 @@ def parse_srs_header(header):
140140
elif header.lower().startswith("epsg:"):
141141
srs = CRS.from_epsg(header.lower()[5:])
142142
else:
143-
log.MM_ERROR('Could not parse coordinates. Bad SRS supplied: %s' % header)
143+
log.MM_ERROR(f'Could not parse coordinates. Bad SRS supplied: {header}')
144144
except RuntimeError as e:
145145
log.MM_ERROR('Uh oh! There seems to be a problem with your coordinates/GCP file.\n\n'
146146
'The line: %s\n\n'

0 commit comments

Comments
 (0)