1

Using piexif I got the DMS of Latitude and longitude which I am trying to convert in decimal degree, but for some images I am getting lattitude value as 184.62583333333333 which is out of the [-90,90] range.

check out the code below,

exif_dict = piexif.load('images/DJI_0026.JPG')
long = 0
latt = 0
value = exif_dict['GPS']
if value:
    lat = value[2]
    lon = value[4]
    for i in range(3):
        if i == 1:
            latt += lat[i][0]/60.0
        elif i == 2:
            latt += lat[i][0]/3600.0
        else:
            latt += lat[i][0]
    for i in range(3):
        if i == 1:
            long += lon[i][0]/60.0
        elif i == 2:
            long += lon[i][0]/3600.0
        else:
            long += lon[i][0]
print(latt, long)

value = {0: (2, 3, 0, 0), 1: b'N', 2: ((19, 1), (8, 1), (595773, 10000)), 3: b'E', 4: ((73, 1), (0, 1), (131775, 10000)), 5: 0, 6: (70989, 1000)}

I am concerned with latitude and longitude, that is stored in value of key 2 and 4.

latitude = 19+8/60.0+595773/3600.0

longitude = 73+0/60.0+131775/3600.0

that is what the output is.

OutPut: 184.62583333333333 109.60416666666666

Please let me know how to normalise the latitude in the range of [-90,90].

Gaurang Patel
  • 172
  • 3
  • 11
  • How is the original EXIF data encoded? – Thierry Lathuille Dec 23 '18 at 09:27
  • @ThierryLathuille, like this {0: (2, 3, 0, 0), 1: b'N', 2: ((19, 1), (8, 1), (595773, 10000)), 3: b'E', 4: ((73, 1), (0, 1), (131775, 10000)), 5: 0, 6: (70989, 1000)} – Gaurang Patel Dec 23 '18 at 09:28
  • When you step through the code using a debugger, at which point do the values differ from what you would expect? Compare the coordinates with those that other programs show. – Roland Illig Dec 23 '18 at 09:31
  • @RolandIllig, I am getting the right output, but I want to normalise the latitude longitude that I am getting, cz when you search on maps there are is no such place with the latitude & longitude. – Gaurang Patel Dec 23 '18 at 09:38

2 Answers2

3

The data as returned by piexif for the GPS coordinates has the following format:

exif_data = {0: (2, 3, 0, 0),
             # Latitude: b'N' or b'S'
             1: b'N', 
             # deg, min, sec as (numerator,denominator) of rationals
             2: ((19, 1), (8, 1), (595773, 10000)),
             # Longitude: b'E' or b'W'
             3: b'E', 
             4: ((73, 1), (0, 1), (131775, 10000)), 
             5: 0, 6: (70989, 1000)}

Latitude and longitude are given as positive, rational values, towards N or S (resp. E or W).

We need to convert the positive values from DMS to decimal, then give them the right sign depending on the direction:

def convert_DMS_tuple(tup):
    d, m, s = [t[0]/t[1] for t in tup]
    degrees = d + m/60 + s/3600
    return degrees

def EXIF_to_lat_long(exif_data):
    # Latitude is counted positive towards N
    lat_sign = 1 if exif_data[1] == b'N' else -1
    lat = lat_sign*convert_DMS_tuple(exif_data[2])

    # Longitude is counted positive towards E
    long_sign = 1 if exif_data[3] == b'E' else -1
    long = long_sign*convert_DMS_tuple(exif_data[4])

    return lat, long

EXIF_to_lat_long(exif_data)
# (19.149882583333333, 73.00366041666666)

You can use this like:

exif_dict = piexif.load('images/DJI_0026.JPG')
value = exif_dict['GPS']
if value:
   print(EXIF_to_lat_long(value))
Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50
1

From the example values you gave, it looks obvious that you should divide val[0] by val[1].

For example, 595773 / 10000 = 59, which makes perfect sense for a second.

By the way, you don't need the for loops. They make your code longer than necessary.

There's probably a reason why value[1] == b'N'. Your current code does not evaluate it though. This means that your code only works for 1/4 of the Earth's surface.

See https://sno.phy.queensu.ca/~phil/exiftool/TagNames/GPS.html for a good overview. Your code should be able to interpret South and West as well.

Roland Illig
  • 40,703
  • 10
  • 88
  • 121
  • latitude is always at number 2 and longitude is always at number 4. – Gaurang Patel Dec 23 '18 at 09:40
  • can you help me how to do that? I am not getting it. – Gaurang Patel Dec 23 '18 at 09:51
  • 1
    @rolandilling is correct. As per [exif2 specs](http://www.exiv2.org/tags.html) and [here](http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf) GPSLatitude Indicates the latitude. The latitude is expressed as three RATIONAL values giving the degrees, minutes, and seconds, respectively. If latitude is expressed as degrees, minutes and seconds, a typical format would be dd/1,mm/1,ss/1. When degrees and minutes are used and, for example, fractions of minutes are given up to two decimal places, the format would be dd/1,mmmm/100,0/1. So, degrees = 19/1, minutes = 8/1 and seconds = 595773/10000 – buran Dec 23 '18 at 10:13
  • *You should not rely on the longitude being always at index 2* — You mean latitude, and that's in the standard. In the page you linked you can see that latitude has tag id 0x0002. – Norrius Dec 23 '18 at 10:15