{"id":1400,"date":"2022-05-11T09:33:17","date_gmt":"2022-05-11T09:33:17","guid":{"rendered":"https:\/\/marcel-jan.eu\/datablog\/?p=1400"},"modified":"2022-05-25T18:30:56","modified_gmt":"2022-05-25T18:30:56","slug":"photo-locations-marker-icons-and-displaying-photos-on-my-map","status":"publish","type":"post","link":"https:\/\/marcel-jan.eu\/datablog\/2022\/05\/11\/photo-locations-marker-icons-and-displaying-photos-on-my-map\/","title":{"rendered":"Photo locations, marker icons and displaying photos on my map"},"content":{"rendered":"<p>When I was finished last week with creating <a href=\"https:\/\/marcel-jan.eu\/datablog\/2022\/05\/04\/making-my-video-location-map-even-better-with-folium\/\">my video location map in Python<\/a>, I thought &#8220;shame I can&#8217;t plot photo locations&#8221;. That&#8217;s because my <a href=\"https:\/\/fujifilm-x.com\/nl-nl\/products\/cameras\/x-t30\/\">Fuji X-T30<\/a> camera doesn&#8217;t store GPS info. When I bought the camera I assumed every modern camera had GPS tagging, so I didn&#8217;t even checked that feature. Too bad. But I also made some photo&#8217;s during my vacations with my humble iPhone 8. And it does have GPS tags. So let&#8217;s plot some photo locations.<\/p>\n<p><!--more--><\/p>\n<h2>Reading GPS tags from JPGs<\/h2>\n<p>GPS tag data is stored in the JPG file itself, in the EXIF metadata. There can be stored a good amount of metadata in that EXIF part of your JPG: GPS location, the direction that you were aiming, your speed at the moment, lighting, lenses, camera type, app used etc.. (This is also the reason why I use the EXIF remover app before I post photos on social media.) To get an impression of metadata stored, upload a JPG to <a href=\"https:\/\/exifdata.com\">exifdata.com<\/a>. The GPS tags will look like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1413\" src=\"https:\/\/marcel-jan.eu\/datablog\/wp-content\/uploads\/2022\/05\/jpg_exif_gpstag-300x179.png\" alt=\"\" width=\"300\" height=\"179\" \/><\/p>\n<p>If you want to read EXIF data with Python there are a LOT of sites with info on how to do that. And they all seem to use different libraries. Not all of them brought me success.\u00a0 The code from <a href=\"https:\/\/developer.here.com\/blog\/getting-started-with-geocoding-exif-image-metadata-in-python3\">this blog by Jayson DeLancey<\/a> did work and I&#8217;ve integrated it into my code. You can best read Jayson&#8217;s blog to learn how it works.<\/p>\n<p>I made some minor changes to Jayson DeLancey&#8217;s version of the code. For example, I didn&#8217;t want to exit if no EXIF data or geodata was found. Like with my video GPS data, the code now creates a dataframe called photodf with a filename, creation date, latitude, longitude and altitude.<\/p>\n<p>&nbsp;<\/p>\n<h2>Different Folium markers<\/h2>\n<p>I wanted the video and photo markers to be clearly different on the map. You&#8217;d think changing the marker colour would do the trick. But it did not. It&#8217;s the icon colour you want to change.<\/p>\n<pre>for index, georow in photodf.iterrows():\r\n    folium.Marker([georow['latitude'], georow['longitude']]\r\n                  , popup=f\"filename: {georow['filename']}&lt;\/br&gt;creationdate: {georow['creationdate']}\"\r\n                  , icon=folium.Icon(color='red')).add_to(my_map)<\/pre>\n<p>But there&#8217;s more you can do with marker icons. You can actually make it into an icon of a camera. Here I have a red icon marker, with a white icon of a camera.<\/p>\n<pre>for index, georow in photodf.iterrows():\r\n    folium.Marker([georow['latitude'], georow['longitude']]\r\n                  , popup=f\"filename: {georow['filename']}&lt;\/br&gt;creationdate: {georow['creationdate']}\"\r\n                  , icon=folium.Icon(color='red', icon_color='white', icon='camera')).add_to(my_map)<\/pre>\n<p>So what icon to choose for the video? These icons are so called glypicons. And there <a href=\"https:\/\/getbootstrap.com\/docs\/3.3\/components\/\">250 to choose from<\/a>. There are ways to load extra icons though. I haven&#8217;t checked that out yet. The closest I got to a video camera icon from this icon set, was the facetime-video. Here we have a blue marker with a white facetime-video icon:<\/p>\n<pre>for index, georow in videodf.iterrows():\r\n    folium.Marker([georow['latitude'], georow['longitude']],\r\n                  popup=f\"filename: {georow['filename']}&lt;\/br&gt;creationdate: {georow['creationdate']}\"\r\n                  , icon=folium.Icon(color='blue', icon_color='white', icon='facetime-video')).add_to(my_map)<\/pre>\n<p>And when all data is loaded and all markers are projected on the map, it looks something like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1401\" src=\"https:\/\/marcel-jan.eu\/datablog\/wp-content\/uploads\/2022\/05\/VDM2021_media_folium1-300x141.png\" alt=\"\" width=\"1017\" height=\"478\" \/><\/p>\n<p>I was so happy when I saw this. And I got to this part with relative ease.<\/p>\n<p>&nbsp;<\/p>\n<h2>Can we do something with the image direction?<\/h2>\n<p>I noticed the iPhone GPS data also has an image direction. I was wondering: is there a way to show on the map which way I shot the image? For example, Folium icons have an angle property. A quick experiment shows that this works:<\/p>\n<pre>for index, georow in photodf.iterrows():\r\n    folium.Marker([georow['latitude'], georow['longitude']]\r\n                  , popup=f\"filename: {georow['filename']}&lt;\/br&gt;creationdate: {georow['creationdate']}\"\r\n                  , icon=folium.Icon(color='red', icon_color='white', icon='camera', angle=30)).add_to(my_map)<\/pre>\n<p>This is the result:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1408\" src=\"https:\/\/marcel-jan.eu\/datablog\/wp-content\/uploads\/2022\/05\/VDM2021_media_photoangle-300x203.png\" alt=\"\" width=\"618\" height=\"418\" \/><\/p>\n<p>Nice, but it would be confusing for the user (being me). The facetime-video icon shows a clear direction, but the camera icon does not.<\/p>\n<p>&nbsp;<\/p>\n<h2>Projecting photos on the map?<\/h2>\n<p>If my wishes are fulfilled this easily, how about taking it to the next step? How about projecting thumbnails of photo&#8217;s on the map, rather than just a marker? Believe it or not, but that is also possible.<\/p>\n<p>It&#8217;s possible, which doesn&#8217;t mean you want this. We&#8217;re talking about reading all my images of 3088 by 2320 pixels here. Even if I downsize them with HTML to fit on the screen, it reads all the images at full resolution.<\/p>\n<p>Still, I can show you the result of just one photo. It will display the photo as a tooltip of a marker. First I have a function to create an img HTML tag. I read the full JPG, and resize it in HTML:<\/p>\n<pre>def make_popup_imgtag(popup_image):\r\n    encoded = base64.b64encode(open(popup_image, 'rb').read())\r\n    html = '&lt;img src=\"data:image\/png;base64,{}\" width=\"400\" height=\"300\"&gt;'.format\r\n    iframe = IFrame(html(encoded.decode('UTF-8')), width=400, height=300)\r\n    popup = folium.Popup(iframe, max_width=400)\r\n    return html, iframe, popup<\/pre>\n<p>Then I take one JPG file, and create the marker for it. You can see I chose a gray marker, so I was able to distinguish it from the other photo markers:<\/p>\n<pre>popup_image = \"Y:\\\\2021\\\\Vercors en Drome 2021\\\\iPhone\\\\IMG_3474.JPG\"\r\npopup_html, popup_iframe, popup_text = make_popup_imgtag(popup_image)\r\n\r\nfolium.Marker(location=[44.69158611111111, 5.986177777777778], tooltip=popup_html, popup=popup_text,\r\n              icon=folium.Icon(color='gray', icon_color='white', icon='camera')).add_to(my_map)<\/pre>\n<p>And here is the result:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1404\" src=\"https:\/\/marcel-jan.eu\/datablog\/wp-content\/uploads\/2022\/05\/2022-05-10_23-10-15-300x199.gif\" alt=\"\" width=\"589\" height=\"391\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>To make this really work, I&#8217;ll probably need to create thumbnail versions of all my photos (and videos, why not?) that I store somewhere for this purpose. But I&#8217;m not working on that now. I&#8217;m a bit hesistant of having subdirectories with massive lists of tiny files in every photo directory. But I can see a future version where you can click on a marker of any photo or video and get to see a thumbnail or a tiny animated gif of the video.<\/p>\n<p>&nbsp;<\/p>\n<h2>Going object oriented<\/h2>\n<p>With all the extra code for reading EXIF data, getting GPS tags, new dataframe and new Folium markers, my code became rather unwieldy. I dediced it was time to clean it up. So I decided making my code object oriented would probably be a good exercise. I never had a lot of training in object oriented programming.<\/p>\n<p>I assumed a Video and a Photo object would be good to program attributes and methods for. At first it was a very frustrating exercise that took me as much time as writing the whole program in the first place. But gradually I was getting the hang of it and I got my code to do the stuff it did before the operation.<\/p>\n<p>&nbsp;<\/p>\n<p>You can find the end result here:<\/p>\n<p><a href=\"https:\/\/github.com\/Marcel-Jan\/media_gpsplot\/blob\/main\/media_gpsplot.py\">https:\/\/github.com\/Marcel-Jan\/media_gpsplot\/blob\/main\/media_gpsplot.py<\/a><\/p>\n<p>A sample result can be found here:<\/p>\n<p><a href=\"https:\/\/github.com\/Marcel-Jan\/media_gpsplot\/blob\/main\/media_gpsplot.html\">https:\/\/github.com\/Marcel-Jan\/media_gpsplot\/blob\/main\/media_gpsplot.html<\/a><\/p>\n<p>I had to rename my Github repo to <em>media<\/em>_gpsplot, rather than <em>video<\/em>_gpsplot. So that changed as well.<\/p>\n<p>&nbsp;<\/p>\n<p>Other blogposts I wrote about geo data in Python:<\/p>\n<p><a href=\"https:\/\/marcel-jan.eu\/datablog\/2022\/05\/23\/adding-the-track-of-my-bike-ride-on-a-folium-map\/\">Adding the track of my bike ride in Folium (Antpaths and Polylines)<\/a><\/p>\n<p><a href=\"https:\/\/marcel-jan.eu\/datablog\/2022\/05\/21\/digging-into-video-files-for-geolocations\/\">Digging into video files for geolocations (Exif data in video files, running OS commands from Python, processing XML)<\/a><\/p>\n<p><a href=\"https:\/\/marcel-jan.eu\/datablog\/2022\/05\/04\/making-my-video-location-map-even-better-with-folium\/\">Making a map of video locations in Folium<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I was finished last week with creating my video location map in Python, I thought &#8220;shame I can&#8217;t plot photo locations&#8221;. That&#8217;s because my Fuji X-T30 camera doesn&#8217;t store GPS info. When I bought the camera I assumed every modern camera had GPS tagging, so I didn&#8217;t even checked [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[191,55,75],"tags":[322,319,325,321,323,326,76,324],"class_list":["post-1400","post","type-post","status-publish","format-standard","hentry","category-data-engineering","category-howto","category-python","tag-exif","tag-folium","tag-glyphicon","tag-jpg","tag-media_gpsplot","tag-object-oriented","tag-python","tag-video-location-map"],"_links":{"self":[{"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/posts\/1400","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/comments?post=1400"}],"version-history":[{"count":7,"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/posts\/1400\/revisions"}],"predecessor-version":[{"id":1443,"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/posts\/1400\/revisions\/1443"}],"wp:attachment":[{"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/media?parent=1400"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/categories?post=1400"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marcel-jan.eu\/datablog\/wp-json\/wp\/v2\/tags?post=1400"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}