some stuff
This commit is contained in:
		
							parent
							
								
									c28496c602
								
							
						
					
					
						commit
						64018561f2
					
				
							
								
								
									
										7
									
								
								pytest.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								pytest.ini
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					[pytest]
 | 
				
			||||||
 | 
					addopts = --ignore=old_tests -s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# collect_ignore = ["old_test"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[pycodestyle]
 | 
				
			||||||
 | 
					# ignore = old_test/* ALL
 | 
				
			||||||
							
								
								
									
										612
									
								
								todo.md
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										612
									
								
								todo.md
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,612 @@
 | 
				
			|||||||
 | 
					# NOW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Media:
 | 
				
			||||||
 | 
					- rewrite set_date...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Test:
 | 
				
			||||||
 | 
					- finish filesystem
 | 
				
			||||||
 | 
					- date_taken
 | 
				
			||||||
 | 
					- geolocation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					move elodie to dozo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check for early morning photos: add test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add --folder-path option %Y-%d-%m/%city/%album
 | 
				
			||||||
 | 
					datetime.today().strftime('%Y-%m-%d')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add %filename
 | 
				
			||||||
 | 
					add edit_exif command?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Add update command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# enhancement
 | 
				
			||||||
 | 
					- acccept Path in get_exiftool
 | 
				
			||||||
 | 
					- Use get_exiftool instead of get metadata:
 | 
				
			||||||
 | 
					    try to do it in get_date_taken...
 | 
				
			||||||
 | 
					media class:
 | 
				
			||||||
 | 
					- Add self.file_path
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Album form folder
 | 
				
			||||||
 | 
					- move to filesystem
 | 
				
			||||||
 | 
					    # TODO implement album from folder here?
 | 
				
			||||||
 | 
					    # folder = os.path.basename(os.path.dirname(source))
 | 
				
			||||||
 | 
					    # album = self.metadata['album']
 | 
				
			||||||
 | 
					    # if album_from_folder and (album is None or album == ''):
 | 
				
			||||||
 | 
					    #     album = folder
 | 
				
			||||||
 | 
					# Update
 | 
				
			||||||
 | 
					use pathlib instead of os.path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Allow update in sort command in same dir if path is the dest dir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENhancement: swap hash db key value: for checking file integrity
 | 
				
			||||||
 | 
					https://github.com/JohannesBuchner/imagehash
 | 
				
			||||||
 | 
					https://github.com/cw-somil/Duplicate-Remover
 | 
				
			||||||
 | 
					https://leons.im/posts/a-python-implementation-of-simhash-algorithm/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Visualy check similar image
 | 
				
			||||||
 | 
					https://www.pluralsight.com/guides/importing-image-data-into-numpy-arrays
 | 
				
			||||||
 | 
					https://stackoverflow.com/questions/56056054/add-check-boxes-to-scrollable-image-in-python
 | 
				
			||||||
 | 
					https://wellsr.com/python/python-image-manipulation-with-pillow-library/
 | 
				
			||||||
 | 
					kitty gird image?
 | 
				
			||||||
 | 
					https://fr.wikibooks.org/wiki/PyQt/PyQt_versus_wxPython
 | 
				
			||||||
 | 
					https://docs.python.org/3/faq/gui.html
 | 
				
			||||||
 | 
					https://docs.opencv.org/3.4/d3/df2/tutorial_py_basic_ops.html
 | 
				
			||||||
 | 
					https://stackoverflow.com/questions/52727332/python-tkinter-create-checkbox-list-from-listbox
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Image gird method:
 | 
				
			||||||
 | 
					matplot
 | 
				
			||||||
 | 
					https://gist.github.com/lebedov/7018889ba47668c64bcf96aee82caec0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tkinter
 | 
				
			||||||
 | 
					https://python-forum.io/thread-22700.html
 | 
				
			||||||
 | 
					https://stackoverflow.com/questions/43326282/how-can-i-use-images-in-a-tkinter-grid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wxwidget
 | 
				
			||||||
 | 
					https://wxpython.org/Phoenix/docs/html/wx.lib.agw.thumbnailctrl.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ability to change metadata to selection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Enhancement: Option to keep existing directory structure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fix: change versvalidion number to 0.x99
 | 
				
			||||||
 | 
					Fix: README
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Refactoring: elodie update: update metadata of destination
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fix: update: fix move files...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Refactoring: Move exiftool config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Checksum:
 | 
				
			||||||
 | 
					FIX: test if checksum remain the same for all files (global check)
 | 
				
			||||||
 | 
					FIX: if dest file already here and checksum d'ont match change name to
 | 
				
			||||||
 | 
					prevent overwriting to file with same dest path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Enhancement: media file, do not filter files, only to prevent error when copying
 | 
				
			||||||
 | 
					fix: Valid file: check for open file error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Enhancement: Add %base_name string key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Refactoring: class get_metadata
 | 
				
			||||||
 | 
					check if as exiF, check exif type...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Interface: show error and warning
 | 
				
			||||||
 | 
					interface: less verbose when no error
 | 
				
			||||||
 | 
					interface: Move default setting to config?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Behavior: Move only by defaut without changing metatdata and filename...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Refactoring: check one time media is valid?
 | 
				
			||||||
 | 
					Refactoring: Unify source and path
 | 
				
			||||||
 | 
					Enhancement: allow nested dir
 | 
				
			||||||
 | 
					Fix: check exclusion for file
 | 
				
			||||||
 | 
					Refactoring: Import perl as submodule?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Enhancement: # setup arguments to exiftool
 | 
				
			||||||
 | 
					https://github.com/andrewning/sortphotos/blob/master/src/sortphotos.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# AFTER
 | 
				
			||||||
 | 
					Enhancement: add walklevel function
 | 
				
			||||||
 | 
					Enhancement: change early morning date sort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO
 | 
				
			||||||
 | 
					Fix: date, make correction in filename if needed
 | 
				
			||||||
 | 
					Check: date from filename
 | 
				
			||||||
 | 
					Options:
 | 
				
			||||||
 | 
					--update-cache|-u
 | 
				
			||||||
 | 
					--date-from-filename
 | 
				
			||||||
 | 
					--location --time
 | 
				
			||||||
 | 
					# --date from folder
 | 
				
			||||||
 | 
					# --date from file
 | 
				
			||||||
 | 
					# -f overwrite metadata
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Add get tag function
 | 
				
			||||||
 | 
					Add --copy alternative
 | 
				
			||||||
 | 
					--auto|-a: a set of option: geolocalisation, best match date, rename, album
 | 
				
			||||||
 | 
					from folder...
 | 
				
			||||||
 | 
					defaut: only move
 | 
				
			||||||
 | 
					# --keep-folder option
 | 
				
			||||||
 | 
					# --rename
 | 
				
			||||||
 | 
					-- no cache mode!!
 | 
				
			||||||
 | 
					--confirm unsure operation
 | 
				
			||||||
 | 
					--interactive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TEST
 | 
				
			||||||
 | 
					    # lat='45.58339'
 | 
				
			||||||
 | 
					    # lon='4.79823'
 | 
				
			||||||
 | 
					        # coordinates ='53.480837, -2.244914'
 | 
				
			||||||
 | 
					        # Alger
 | 
				
			||||||
 | 
					        # coords=(36.752887, 3.042048)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					https://www.gitmemory.com/issue/pallets/click/843/634305917
 | 
				
			||||||
 | 
					https://github.com/pallets/click/issues/843
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # import unittest
 | 
				
			||||||
 | 
					    # import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # from thing.__main__ import cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # class TestCli(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #     @pytest.fixture(autouse=True)
 | 
				
			||||||
 | 
					    #     def capsys(self, capsys):
 | 
				
			||||||
 | 
					    #         self.capsys = capsys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #     def test_cli(self):
 | 
				
			||||||
 | 
					    #         with pytest.raises(SystemExit) as ex:
 | 
				
			||||||
 | 
					    #             cli(["create", "--name", "test"])
 | 
				
			||||||
 | 
					    #         self.assertEqual(ex.value.code, 0)
 | 
				
			||||||
 | 
					    #         out, err = self.capsys.readouterr()
 | 
				
			||||||
 | 
					    #         self.assertEqual(out, "Succesfully created test\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dev
 | 
				
			||||||
 | 
					# mode ~/.elodie ~/.config/elodie
 | 
				
			||||||
 | 
					# location selection buggy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO:
 | 
				
			||||||
 | 
					# /home/cedric/src/elodie/elodie/media/photo.py(86)get_date_taken()
 | 
				
			||||||
 | 
					#      85         # TODO potential bu for old photo below 1970...
 | 
				
			||||||
 | 
					# ---> 86         if(seconds_since_epoch == 0):
 | 
				
			||||||
 | 
					#      87             return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def walklevel(some_dir, level=1):
 | 
				
			||||||
 | 
					    some_dir = some_dir.rstrip(os.path.sep)
 | 
				
			||||||
 | 
					    assert os.path.isdir(some_dir)
 | 
				
			||||||
 | 
					    num_sep = some_dir.count(os.path.sep)
 | 
				
			||||||
 | 
					    for root, dirs, files in os.walk(some_dir):
 | 
				
			||||||
 | 
					        yield root, dirs, files
 | 
				
			||||||
 | 
					        num_sep_this = root.count(os.path.sep)
 | 
				
			||||||
 | 
					        if num_sep + level <= num_sep_this:
 | 
				
			||||||
 | 
					            del dirs[:]
 | 
				
			||||||
 | 
					49/2: y=walklevel('/home/cedric', level=1)
 | 
				
			||||||
 | 
					49/3: next(y)
 | 
				
			||||||
 | 
					49/4: next(y)
 | 
				
			||||||
 | 
					49/5: next(y)
 | 
				
			||||||
 | 
					49/6: next(y)
 | 
				
			||||||
 | 
					49/7: next(y)
 | 
				
			||||||
 | 
					49/8: y=walklevel('/home/cedric', level=0)
 | 
				
			||||||
 | 
					49/9: next(y)
 | 
				
			||||||
 | 
					49/10: next(y)
 | 
				
			||||||
 | 
					49/11: y=walklevel('/home/cedric/.test/Nexcloud/', level=0)
 | 
				
			||||||
 | 
					49/12:
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def walklevel(some_dir, level=1):
 | 
				
			||||||
 | 
					    some_dir = some_dir.rstrip(os.path.sep)
 | 
				
			||||||
 | 
					    assert os.path.isdir(some_dir)
 | 
				
			||||||
 | 
					    num_sep = some_dir.count(os.path.sep)
 | 
				
			||||||
 | 
					    for root, dirs, files in os.walk(some_dir):
 | 
				
			||||||
 | 
					        yield root, dirs, files
 | 
				
			||||||
 | 
					        num_sep_this = root.count(os.path.sep)
 | 
				
			||||||
 | 
					        if num_sep + level <= num_sep_this:
 | 
				
			||||||
 | 
					            print dirs, files
 | 
				
			||||||
 | 
					49/13:
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def walklevel(some_dir, level=1):
 | 
				
			||||||
 | 
					    some_dir = some_dir.rstrip(os.path.sep)
 | 
				
			||||||
 | 
					    assert os.path.isdir(some_dir)
 | 
				
			||||||
 | 
					    num_sep = some_dir.count(os.path.sep)
 | 
				
			||||||
 | 
					    for root, dirs, files in os.walk(some_dir):
 | 
				
			||||||
 | 
					        yield root, dirs, files
 | 
				
			||||||
 | 
					        num_sep_this = root.count(os.path.sep)
 | 
				
			||||||
 | 
					        if num_sep + level <= num_sep_this:
 | 
				
			||||||
 | 
					            print(dirs, files)
 | 
				
			||||||
 | 
					49/14: y=walklevel('/home/cedric/.test/Nexcloud/', level=0)
 | 
				
			||||||
 | 
					49/15: next(y)
 | 
				
			||||||
 | 
					49/16: next(y)
 | 
				
			||||||
 | 
					49/17: y=walklevel('/home/cedric/.test/Nexcloud/', level=0)
 | 
				
			||||||
 | 
					49/18:
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def walklevel(some_dir, level=1):
 | 
				
			||||||
 | 
					    some_dir = some_dir.rstrip(os.path.sep)
 | 
				
			||||||
 | 
					    assert os.path.isdir(some_dir)
 | 
				
			||||||
 | 
					    num_sep = some_dir.count(os.path.sep)
 | 
				
			||||||
 | 
					    for root, dirs, files in os.walk(some_dir):
 | 
				
			||||||
 | 
					        yield root, dirs, files
 | 
				
			||||||
 | 
					        num_sep_this = root.count(os.path.sep)
 | 
				
			||||||
 | 
					49/19: y=walklevel('/home/cedric/.test/Nexcloud/', level=0)
 | 
				
			||||||
 | 
					49/20: next(y)
 | 
				
			||||||
 | 
					49/21: next(y)
 | 
				
			||||||
 | 
					49/22: y=walklevel('/home/cedric/.test/Nexcloud/', level=2)
 | 
				
			||||||
 | 
					49/23: next(y)
 | 
				
			||||||
 | 
					49/24: next(y)
 | 
				
			||||||
 | 
					49/25: y=walklevel('/home/cedric/.test/las canarias 2012/', level=2)
 | 
				
			||||||
 | 
					49/26: next(y)
 | 
				
			||||||
 | 
					49/27: next(y)
 | 
				
			||||||
 | 
					49/28: next(y)
 | 
				
			||||||
 | 
					49/29: next(y)
 | 
				
			||||||
 | 
					49/30: y=walklevel('/home/cedric/.test/las canarias 2012/', level=0)
 | 
				
			||||||
 | 
					49/31: next(y)
 | 
				
			||||||
 | 
					49/32: next(y)
 | 
				
			||||||
 | 
					49/33: next(y)
 | 
				
			||||||
 | 
					49/34:
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def walklevel(some_dir, level=1):
 | 
				
			||||||
 | 
					    some_dir = some_dir.rstrip(os.path.sep)
 | 
				
			||||||
 | 
					    assert os.path.isdir(some_dir)
 | 
				
			||||||
 | 
					    num_sep = some_dir.count(os.path.sep)
 | 
				
			||||||
 | 
					    for root, dirs, files in os.walk(some_dir):
 | 
				
			||||||
 | 
					        yield root, dirs, files
 | 
				
			||||||
 | 
					        num_sep_this = root.count(os.path.sep)
 | 
				
			||||||
 | 
					        if num_sep + level <= num_sep_this:
 | 
				
			||||||
 | 
					            print('fuck')
 | 
				
			||||||
 | 
					49/35: y=walklevel('/home/cedric/.test/las canarias 2012/', level=0)
 | 
				
			||||||
 | 
					49/36: next(y)
 | 
				
			||||||
 | 
					49/37: next(y)
 | 
				
			||||||
 | 
					49/38: next(y)
 | 
				
			||||||
 | 
					64/1:  a=os.walk('/home/cedric/.test/las canarias 2012')
 | 
				
			||||||
 | 
					64/2: import os
 | 
				
			||||||
 | 
					64/3:  a=os.walk('/home/cedric/.test/las canarias 2012')
 | 
				
			||||||
 | 
					64/4: next(a)
 | 
				
			||||||
 | 
					64/5: next(a)
 | 
				
			||||||
 | 
					64/6: os.path.sep
 | 
				
			||||||
 | 
					64/7: os.path.relpath('/home/cedric/.test/las canarias 2012/private', 'private')
 | 
				
			||||||
 | 
					64/8: os.path.relpath('/home/cedric/.test/las canarias 2012', 'private')
 | 
				
			||||||
 | 
					64/9: os.path.relpath('/home/cedric/.test/las canarias 2012/private', '/home/cedric/.test/las canarias 2012')
 | 
				
			||||||
 | 
					64/10: b='test'
 | 
				
			||||||
 | 
					64/11: a='private'
 | 
				
			||||||
 | 
					64/12: a+b
 | 
				
			||||||
 | 
					64/13:  os.path.join(a,b,b)
 | 
				
			||||||
 | 
					64/14: !True
 | 
				
			||||||
 | 
					64/15: not True
 | 
				
			||||||
 | 
					64/16: a=TRue
 | 
				
			||||||
 | 
					64/17: a=True
 | 
				
			||||||
 | 
					64/18: not a
 | 
				
			||||||
 | 
					77/1:
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_location(geotags):
 | 
				
			||||||
 | 
					    coords = get_coordinates(geotags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uri = 'https://revgeocode.search.hereapi.com/v1/revgeocode'
 | 
				
			||||||
 | 
					    headers = {}
 | 
				
			||||||
 | 
					    params = {
 | 
				
			||||||
 | 
					        'apiKey': os.environ['API_KEY'],
 | 
				
			||||||
 | 
					        'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					        'lang': 'en-US',
 | 
				
			||||||
 | 
					        'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    response = requests.get(uri, headers=headers, params=params)
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        response.raise_for_status()
 | 
				
			||||||
 | 
					        return response.json()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    except requests.exceptions.HTTPError as e:
 | 
				
			||||||
 | 
					        print(str(e))
 | 
				
			||||||
 | 
					        return {}
 | 
				
			||||||
 | 
					77/2: cd ~/.test/
 | 
				
			||||||
 | 
					77/3: ls
 | 
				
			||||||
 | 
					77/4: cd 2021-02-Feb/
 | 
				
			||||||
 | 
					77/5: ls
 | 
				
			||||||
 | 
					77/6: cd Villeurbanne/
 | 
				
			||||||
 | 
					77/7: ls
 | 
				
			||||||
 | 
					77/8: ls -l
 | 
				
			||||||
 | 
					77/9: exif = get_exif('2021-02-24_09-33-29-20210305_081001_01.mp4')
 | 
				
			||||||
 | 
					77/10:
 | 
				
			||||||
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_exif(filename):
 | 
				
			||||||
 | 
					    image = Image.open(filename)
 | 
				
			||||||
 | 
					    image.verify()
 | 
				
			||||||
 | 
					    return image._getexif()
 | 
				
			||||||
 | 
					77/11: exif = get_exif('2021-02-24_09-33-29-20210305_081001_01.mp4')
 | 
				
			||||||
 | 
					77/12: ..
 | 
				
			||||||
 | 
					77/13: cd ..
 | 
				
			||||||
 | 
					77/14: ls
 | 
				
			||||||
 | 
					77/15: cd ..
 | 
				
			||||||
 | 
					77/16: ls
 | 
				
			||||||
 | 
					77/17: cd 2021-03-Mar/
 | 
				
			||||||
 | 
					77/18: cd Villeurbanne/
 | 
				
			||||||
 | 
					77/19: ls
 | 
				
			||||||
 | 
					77/20: exif = get_exif('2021-03-09_09-58-42-img_20210309_105842.jpg')
 | 
				
			||||||
 | 
					77/21: exif
 | 
				
			||||||
 | 
					77/22:
 | 
				
			||||||
 | 
					def get_geotagging(exif):
 | 
				
			||||||
 | 
					    if not exif:
 | 
				
			||||||
 | 
					        raise ValueError("No EXIF metadata found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    geotagging = {}
 | 
				
			||||||
 | 
					    for (idx, tag) in TAGS.items():
 | 
				
			||||||
 | 
					        if tag == 'GPSInfo':
 | 
				
			||||||
 | 
					            if idx not in exif:
 | 
				
			||||||
 | 
					                raise ValueError("No EXIF geotagging found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (key, val) in GPSTAGS.items():
 | 
				
			||||||
 | 
					                if key in exif[idx]:
 | 
				
			||||||
 | 
					                    geotagging[val] = exif[idx][key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return geotagging
 | 
				
			||||||
 | 
					77/23: get_geotagging(exif)
 | 
				
			||||||
 | 
					77/24: from PIL.ExifTags import TAGS
 | 
				
			||||||
 | 
					77/25:
 | 
				
			||||||
 | 
					def get_labeled_exif(exif):
 | 
				
			||||||
 | 
					    labeled = {}
 | 
				
			||||||
 | 
					    for (key, val) in exif.items():
 | 
				
			||||||
 | 
					        labeled[TAGS.get(key)] = val
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return labeled
 | 
				
			||||||
 | 
					77/26: get_geotagging(exif)
 | 
				
			||||||
 | 
					77/27: from PIL.ExifTags import GPSTAGS
 | 
				
			||||||
 | 
					77/28: get_geotagging(exif)
 | 
				
			||||||
 | 
					77/29: geotags = get_geotagging(exif)
 | 
				
			||||||
 | 
					77/30: get_location(geotags)
 | 
				
			||||||
 | 
					77/31:
 | 
				
			||||||
 | 
					def get_decimal_from_dms(dms, ref):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    degrees = dms[0][0] / dms[0][1]
 | 
				
			||||||
 | 
					    minutes = dms[1][0] / dms[1][1] / 60.0
 | 
				
			||||||
 | 
					    seconds = dms[2][0] / dms[2][1] / 3600.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ref in ['S', 'W']:
 | 
				
			||||||
 | 
					        degrees = -degrees
 | 
				
			||||||
 | 
					        minutes = -minutes
 | 
				
			||||||
 | 
					        seconds = -seconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return round(degrees + minutes + seconds, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_coordinates(geotags):
 | 
				
			||||||
 | 
					    lat = get_decimal_from_dms(geotags['GPSLatitude'], geotags['GPSLatitudeRef'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lon = get_decimal_from_dms(geotags['GPSLongitude'], geotags['GPSLongitudeRef'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (lat,lon)
 | 
				
			||||||
 | 
					77/32: get_geotagging(exif)
 | 
				
			||||||
 | 
					77/33: get_location(geotags)
 | 
				
			||||||
 | 
					77/34: from geopy.geocoders import Here
 | 
				
			||||||
 | 
					78/1: from geopy.geocoders import Here
 | 
				
			||||||
 | 
					78/3:
 | 
				
			||||||
 | 
					78/4: get_exif
 | 
				
			||||||
 | 
					78/5: ls
 | 
				
			||||||
 | 
					78/6: cd ~/.test
 | 
				
			||||||
 | 
					78/7: ls
 | 
				
			||||||
 | 
					78/8: cd 2021-03-Mar/
 | 
				
			||||||
 | 
					78/9: ls
 | 
				
			||||||
 | 
					78/10: cd Villeurbanne/
 | 
				
			||||||
 | 
					78/11: get_exif('2021-03-04_11-50-32-img_20210304_125032.jpg')
 | 
				
			||||||
 | 
					78/12: exif=get_exif('2021-03-04_11-50-32-img_20210304_125032.jpg')
 | 
				
			||||||
 | 
					78/13: get_geotagging(exif)
 | 
				
			||||||
 | 
					78/14:
 | 
				
			||||||
 | 
					from PIL.ExifTags import GPSTAGS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_geotagging(exif):
 | 
				
			||||||
 | 
					    if not exif:
 | 
				
			||||||
 | 
					        raise ValueError("No EXIF metadata found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    geotagging = {}
 | 
				
			||||||
 | 
					    for (idx, tag) in TAGS.items():
 | 
				
			||||||
 | 
					        if tag == 'GPSInfo':
 | 
				
			||||||
 | 
					            if idx not in exif:
 | 
				
			||||||
 | 
					                raise ValueError("No EXIF geotagging found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (key, val) in GPSTAGS.items():
 | 
				
			||||||
 | 
					                if key in exif[idx]:
 | 
				
			||||||
 | 
					                    geotagging[val] = exif[idx][key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return geotagging
 | 
				
			||||||
 | 
					78/15: geotags = get_geotagging(exif)
 | 
				
			||||||
 | 
					78/17: geotags = get_geotagging(exif)
 | 
				
			||||||
 | 
					78/18: get_coordinates(geotags)
 | 
				
			||||||
 | 
					78/19:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					78/23: get_location(geotags)
 | 
				
			||||||
 | 
					78/24:
 | 
				
			||||||
 | 
					78/25: get_location(geotags)
 | 
				
			||||||
 | 
					78/26:
 | 
				
			||||||
 | 
					def get_decimal_from_dms(dms, ref):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    degrees = dms[0][0] / dms[0][1]
 | 
				
			||||||
 | 
					    minutes = dms[1][0] / dms[1][1] / 60.0
 | 
				
			||||||
 | 
					    seconds = dms[2][0] / dms[2][1] / 3600.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ref in ['S', 'W']:
 | 
				
			||||||
 | 
					        degrees = -degrees
 | 
				
			||||||
 | 
					        minutes = -minutes
 | 
				
			||||||
 | 
					        seconds = -seconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return round(degrees + minutes + seconds, 5)
 | 
				
			||||||
 | 
					78/27: get_location(geotags)
 | 
				
			||||||
 | 
					78/28:
 | 
				
			||||||
 | 
					def get_decimal_from_dms(dms, ref):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    degrees = dms[0]
 | 
				
			||||||
 | 
					    minutes = dms[1] / 60.0
 | 
				
			||||||
 | 
					    seconds = dms[2] / 3600.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ref in ['S', 'W']:
 | 
				
			||||||
 | 
					        degrees = -degrees
 | 
				
			||||||
 | 
					        minutes = -minutes
 | 
				
			||||||
 | 
					        seconds = -seconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return round(degrees + minutes + seconds, 5)
 | 
				
			||||||
 | 
					78/29: get_location(geotags)
 | 
				
			||||||
 | 
					78/30: exif
 | 
				
			||||||
 | 
					78/31: get_geotagging(exif)
 | 
				
			||||||
 | 
					78/32: geotags = get_geotagging(exif)
 | 
				
			||||||
 | 
					78/33: get_coordinates(geotags)
 | 
				
			||||||
 | 
					78/34: geotags = get_geotagging(exif)
 | 
				
			||||||
 | 
					78/35: get_location(geotags)
 | 
				
			||||||
 | 
					78/36: get_coordinates(geotags)
 | 
				
			||||||
 | 
					78/37: coords = get_coordinates(geotags)
 | 
				
			||||||
 | 
					78/38: coords
 | 
				
			||||||
 | 
					78/39: uri = 'https://revgeocode.search.hereapi.com/v1/revgeocode'
 | 
				
			||||||
 | 
					78/40:
 | 
				
			||||||
 | 
					headers = {}
 | 
				
			||||||
 | 
					    params = {
 | 
				
			||||||
 | 
					        'apiKey': os.environ['API_KEY'],
 | 
				
			||||||
 | 
					        'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					        'lang': 'en-US',
 | 
				
			||||||
 | 
					        'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					78/41: headers = {}
 | 
				
			||||||
 | 
					78/42:
 | 
				
			||||||
 | 
					params = {
 | 
				
			||||||
 | 
					    'apiKey': os.environ['API_KEY'],
 | 
				
			||||||
 | 
					    'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					    'lang': 'en-US',
 | 
				
			||||||
 | 
					    'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					78/43:
 | 
				
			||||||
 | 
					params = {
 | 
				
			||||||
 | 
					    'apiKey': os.environ['API_KEY'],
 | 
				
			||||||
 | 
					    'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					    'lang': 'en-US',
 | 
				
			||||||
 | 
					    'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					78/44: API_KEY=m5aGo8xGe4LLhxeKZYpHr2MPXGN2aDhe
 | 
				
			||||||
 | 
					78/45: API_KEY='m5aGo8xGe4LLhxeKZYpHr2MPXGN2aDhe'
 | 
				
			||||||
 | 
					78/46:
 | 
				
			||||||
 | 
					params = {
 | 
				
			||||||
 | 
					    'apiKey': os.environ['API_KEY'],
 | 
				
			||||||
 | 
					    'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					    'lang': 'en-US',
 | 
				
			||||||
 | 
					    'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					78/47: API_KEY='m5aGo8xGe4LLhxeKZYpHr2MPXGN2aDhe'
 | 
				
			||||||
 | 
					78/48:
 | 
				
			||||||
 | 
					params = {
 | 
				
			||||||
 | 
					    'apiKey': os.environ['API_KEY'],
 | 
				
			||||||
 | 
					    'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					    'lang': 'en-US',
 | 
				
			||||||
 | 
					    'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					78/49:
 | 
				
			||||||
 | 
					params = {
 | 
				
			||||||
 | 
					    'apiKey': os.environ['m5aGo8xGe4LLhxeKZYpHr2MPXGN2aDhe'],
 | 
				
			||||||
 | 
					    'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					    'lang': 'en-US',
 | 
				
			||||||
 | 
					    'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					78/50: %load_ext autotime
 | 
				
			||||||
 | 
					78/51:
 | 
				
			||||||
 | 
					import pandas as pd
 | 
				
			||||||
 | 
					import geopandas as gpd
 | 
				
			||||||
 | 
					import geopy
 | 
				
			||||||
 | 
					from geopy.geocoders import Nominatim
 | 
				
			||||||
 | 
					from geopy.extra.rate_limiter import RateLimiterimport matplotlib.pyplot as plt
 | 
				
			||||||
 | 
					import plotly_express as pximport tqdm
 | 
				
			||||||
 | 
					from tqdm._tqdm_notebook import tqdm_notebook
 | 
				
			||||||
 | 
					78/52:
 | 
				
			||||||
 | 
					import pandas as pd
 | 
				
			||||||
 | 
					import geopandas as gpd
 | 
				
			||||||
 | 
					import geopy
 | 
				
			||||||
 | 
					from geopy.geocoders import Nominatim
 | 
				
			||||||
 | 
					from geopy.extra.rate_limiter import RateLimiterimport matplotlib.pyplot as plt
 | 
				
			||||||
 | 
					import plotly_express as px
 | 
				
			||||||
 | 
					import pandas as pd
 | 
				
			||||||
 | 
					import geopandas as gpd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					filename='2021-02-24_09-33-29-20210305_081001_01.mp4'
 | 
				
			||||||
 | 
					def get_exif(filename):
 | 
				
			||||||
 | 
					    image = Image.open(filename)
 | 
				
			||||||
 | 
					    image.verify()
 | 
				
			||||||
 | 
					    return image._getexif()
 | 
				
			||||||
 | 
					exif=get_exif(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from PIL.ExifTags import TAGS
 | 
				
			||||||
 | 
					from PIL.ExifTags import GPSTAGS
 | 
				
			||||||
 | 
					def get_geotagging(exif):
 | 
				
			||||||
 | 
					    if not exif:
 | 
				
			||||||
 | 
					        raise ValueError("No EXIF metadata found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    geotagging = {}
 | 
				
			||||||
 | 
					    for (idx, tag) in TAGS.items():
 | 
				
			||||||
 | 
					        if tag == 'GPSInfo':
 | 
				
			||||||
 | 
					            if idx not in exif:
 | 
				
			||||||
 | 
					                raise ValueError("No EXIF geotagging found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (key, val) in GPSTAGS.items():
 | 
				
			||||||
 | 
					                if key in exif[idx]:
 | 
				
			||||||
 | 
					                    geotagging[val] = exif[idx][key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return geotagging
 | 
				
			||||||
 | 
					geotags = get_geotagging(exif)
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_location(geotags):
 | 
				
			||||||
 | 
					    coords = get_coordinates(geotags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uri = 'https://revgeocode.search.hereapi.com/v1/revgeocode'
 | 
				
			||||||
 | 
					    headers = {}
 | 
				
			||||||
 | 
					    params = {
 | 
				
			||||||
 | 
					        'apiKey': os.environ['API_KEY'],
 | 
				
			||||||
 | 
					        'at': "%s,%s" % coords,
 | 
				
			||||||
 | 
					        'lang': 'en-US',
 | 
				
			||||||
 | 
					        'limit': 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    response = requests.get(uri, headers=headers, params=params)
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        response.raise_for_status()
 | 
				
			||||||
 | 
					        return response.json()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    except requests.exceptions.HTTPError as e:
 | 
				
			||||||
 | 
					        print(str(e))
 | 
				
			||||||
 | 
					        return {}
 | 
				
			||||||
 | 
					def get_coordinates(geotags):
 | 
				
			||||||
 | 
					    lat = get_decimal_from_dms(geotags['GPSLatitude'], geotags['GPSLatitudeRef'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lon = get_decimal_from_dms(geotags['GPSLongitude'], geotags['GPSLongitudeRef'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (lat,lon)
 | 
				
			||||||
 | 
					coords = get_coordinates(geotags)
 | 
				
			||||||
 | 
					import geopy
 | 
				
			||||||
 | 
					from geopy.geocoders import Nominatim
 | 
				
			||||||
 | 
					locator = Nominatim(user_agent='myGeocoder')
 | 
				
			||||||
 | 
					# coordinates ='53.480837, -2.244914'
 | 
				
			||||||
 | 
					lat='45.58339'
 | 
				
			||||||
 | 
					lon='4.79823'
 | 
				
			||||||
 | 
					coords = lat + ',' + lon
 | 
				
			||||||
 | 
					locator.reverse(coords)
 | 
				
			||||||
 | 
					location =locator.reverse(coords)
 | 
				
			||||||
 | 
					location.address.split(',')
 | 
				
			||||||
 | 
					city=location.address.split(',')[1].strip()
 | 
				
			||||||
 | 
					country=location.address.split(',')[7].strip()
 | 
				
			||||||
 | 
					location.raw
 | 
				
			||||||
 | 
					rint
 | 
				
			||||||
 | 
					country=location.raw['address']['country']
 | 
				
			||||||
 | 
					city=location.raw['address']['village']
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user