pythonexifraspberry-pi-zeropicamera

Python PiCamera - How do I format the coordinates for the Exif?


I just got my first Raspberry Pi product last week. I got a Raspberry Pi Zero W, and a PiCamera. I created a program (to be ran each day by crontab) that will take a photo, store the photo locally, transfer a copy of the photo to a local server, make a CSV log of the photo, and make an easily readable text daily report. I've gotten almost everything working correctly, but I have one particular issue I can't seem to figure out.

I'm using the Python PiCamera library to capture the photos everyday, and I wanted to set some static GPS data to each photo's EXIF metadata. (The GPS data needs to be static because the Pi is suction cupped to a window and wont be moving for at least a year) The issue I need help with is that I do not know how EXACTLY I need to format my GPS data for PiCamera's exif_tag property. Here are some of the formats I've tried and have not given me appropriate results:

Attempt #1 - Float

camera.exif_tags["GPS.GPSLatitude"] = 41.1027
camera.exif_tags["GPS.GPSLongitude"] = -85.1362

I get this error:

Traceback (most recent call last):
  File "main.py", line 13, in <module>
    camera.capture(local_path)
  File "/usr/lib/python3/dist-packages/picamera/camera.py", line 1418, in capture
    encoder.start(output)
  File "/usr/lib/python3/dist-packages/picamera/encoders.py", line 1125, in start
    self._add_exif_tag(tag, value)
  File "/usr/lib/python3/dist-packages/picamera/encoders.py", line 1097, in _add_exif_tag
    ct.sizeof(mmal.MMAL_PARAMETER_EXIF_T) + len(tag) + len(value) + 1)
TypeError: object of type 'float' has no len()

Attempt #2 - String

camera.exif_tags["GPS.GPSLatitude"] = "41.1027"
camera.exif_tags["GPS.GPSLongitude"] = "-85.1362"

No error is produced when running this code, however the output data from the exif after the image is captured is still inaccurate:

Latitude            |0.040
Longitude           |3162715.1775

Follow Up Attempts - Other Strings

# Style 1
camera.exif_tags["GPS.GPSLatitude"] = "(41) (6) (10.711)"
camera.exif_tags["GPS.GPSLongitude"] = "(85) (8) (8.968)"

# This produces
Latitude            |1.00
Longitude           |1.00

# Style 2
camera.exif_tags["GPS.GPSLatitude"] = "41 6 10.711"
camera.exif_tags["GPS.GPSLongitude"] = "85 8 8.968"

# This produces
Latitude            |6.8
Longitude           |10.6

# Style 3
camera.exif_tags["GPS.GPSLatitude"] = "41, 6, 10.711"
camera.exif_tags["GPS.GPSLongitude"] = "85, 8, 8.968"

#This produces
Latitude            |6.8, 0.014, 1.000
Longitude           |10.6, 0.008, 2.141837875

So, in short, can anyone help me by providing me with the means to format my strings? I am at a complete loss. The documentation for PiCamera only lists the different tags but does not explain how to format each of them.


Solution

  • Alright, so after several more test cases, a couple hours of research, and finally posting an issue on the PiCamera GitHub repo I finally figured it out. There is no direct documentation on this particular part of the PiCamera library as stated in my question. But someone on the repo was able to point me to the RaspiStill repo on adding GPS exif data, which is written in C. I've never completely learned C and my C++ skills are a bit rusty, but it gave me an idea. The end result came out to this:

    camera.exif_tags["GPS.GPSLatitude"] = "41/1,6/1,9577/1000"
    camera.exif_tags["GPS.GPSLongitude"] = "85/1,8/1,10223/1000"
    

    When looking over the RaspiStill repo it got me thinking of how you would use the commands in the terminal to set exif data, so I looked up how to set the coordinates via RaspiStill and found this documentation which gave an example.

    RaspiStill Documentation

    Some examples of how to represent the data in the form of degrees, minutes, and seconds:

    1. 52 = 52 / 1 (52 units)
    2. 40.44 = 4044 / 100 (4044 hundredths)
    3. 52.97790 = 52977900 / 1000000 (52977900 millionths)
    4. 0 = 0/1

    This is the source of where I found how to do the above "calculations":

    Geotag - Exif Data

    Hopefully this can help someone else too.