https://bugs.kde.org/show_bug.cgi?id=366286

georg.li...@t-online.de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|5.0.0                       |7.8.0

--- Comment #2 from georg.li...@t-online.de ---
This is a super-old feature request from myself. I meanwhile coded a python
script to reverse geocode outside of digikam. I include the code here for
further use. Unfortunately I am not able to code in C++ and thus to contribute
directly. The reverse geocoding is not super-perfect but gives reasonable
results for sightseeing and hiking.

It uses  gmaps to set or correct the gps determined elevation.  Nominatim and
Geonames services are used to collect relevant information for tagging. The two
most abundant entries are then selected for tagging into the IPTC fields.



def reverse(path_file, force=False):  # Force will overwrite existing
definitions
    APIKEY = "please order by yourself"
    gmaps = googlemaps.Client(key=APIKEY)
    lang = "de"  # language used for Nominatin Service
    tolerance_elevation = 100
    slowdown = 1  # interval to slowdown request

    metadata = GExiv2.Metadata(path_file)
    if 'Xmp.photoshop.CaptionWriter' in metadata and force == False:  
        if 'Nominatim & GeoNames' in metadata['Xmp.photoshop.CaptionWriter']:
            logging.info('Skipping already processed file %s' % path_file)
            return

    lat = metadata.try_get_gps_latitude()
    lon = metadata.try_get_gps_longitude()
    if lat == 0 and lon == 0:
        logging.warning("Nothing to do since no valid GPS coordinates in file
%s" % path_file)
        return

    logging.info('Processing file %s' % path_file)

    elevation = round(gmaps.elevation((lat, lon))[0]["elevation"], 0)
    gps_elevation = metadata.try_get_gps_altitude()
    true_elevation = gps_elevation  # assume first picture data
    logging.info('gps elevation: %s \tgmaps elevation: %s' % (gps_elevation,
elevation))
    if gps_elevation <= 0.0:  # no valid elevation
        true_elevation = elevation
        logging.info("No valid elevation data in file, elevation set to gmaps
value %s", elevation)
        metadata.try_set_gps_info(lon, lat, true_elevation)
    elif abs(gps_elevation - elevation) > tolerance_elevation:  # too strong
deviation
        true_elevation = int(elevation)
        logging.info("Too strong deviation, elevation corrected to gmaps value
%s", elevation)
        metadata.set_gps_info(lon, lat, true_elevation)

    query = "%15.12f,%15.12f" % (lat, lon)

    # Nominatim service
    nominatim_dict = {}
    geolocator = Nominatim(timeout=60, user_agent="reverse")
    location = geolocator.reverse(query, language=lang)  # work-around

    for attribute in ['country', 'village', 'city', 'town', 'historic',
'tourism', 'neighbourhood', 'amenity',
                      'locality']:
        try:
            location.raw["address"][attribute]
        except:
            nominatim_dict[attribute] = ''
        else:
            nominatim_dict[attribute] = location.raw["address"][attribute]
    logging.info('Nomatim %s %s' % (location.raw["address"], nominatim_dict))

    # Geonames service
    geonames_dict = {}
    geolocator = GeoNames(username="biokomiker")
    try:
        location = geolocator.reverse(query, find_nearby_type="findNearby",
exactly_one=False)
    except GeocoderTimedOut as e:
        logging.debug("Error: geocode failed on input %s with message %s" %
(query, e.message))
        return

    for attribute in ['toponymName', 'name']:
        try:
            location[0].raw[attribute]
        except:
            geonames_dict[attribute] = ''
        else:
            geonames_dict[attribute] = location[0].raw[attribute]

    logging.info('Geonames %s %s' % (location[0].raw, geonames_dict))

    city_village = nominatim_dict['village'] + nominatim_dict['city'] +
nominatim_dict['town']

    ort = Counter(
        [nominatim_dict[k] for k in ['historic', 'tourism', 'neighbourhood',
'amenity', 'locality']] + [geonames_dict[k]
                                                                               
                        for k in
                                                                               
                        ['toponymName',
                                                                               
                         'name']])
    ort.pop('')
    try:
        final_ort = ort.most_common(2)[0][0] + ' / ' + ort.most_common(2)[1][0]
    except:
        final_ort = ort.most_common(1)[0][0]

    IPTC = 'Iptc.Application2.'

    metadata[IPTC + 'City'] = city_village
    metadata['Xmp.photoshop.City'] = city_village
    metadata[IPTC + 'CountryName'] = nominatim_dict['country']
    metadata['Xmp.photoshop.Country'] = nominatim_dict['country']

    metadata.try_clear_tag(IPTC + 'LocationName')
    metadata.try_clear_tag('Xmp.iptc.Location')
    metadata.set_tag_string(IPTC + 'LocationName', final_ort)
    metadata.set_tag_string('Xmp.iptc.Location', final_ort)

    now = datetime.datetime.now()
    metadata['Xmp.photoshop.CaptionWriter'] = 'Nominatim & GeoNames @ %s-%s-%s'
% (now.year, now.month, now.day)
    metadata.save_file()
    logging.info("\nFinal annotation:\nOrt:          %s \nCity/Village: %s
\nCountry:      %s \nElevation:    %s " % (
    metadata[IPTC + 'LocationName'], metadata[IPTC + 'City'], metadata[IPTC +
'CountryName'], true_elevation))
    print("\nFinal annotation\nOrt:          %s \nCity/Village: %s \nCountry:  
   %s \nElevation:    %s " % (
    metadata[IPTC + 'LocationName'], metadata[IPTC + 'City'], metadata[IPTC +
'CountryName'], true_elevation))
    sleep(slowdown)

    return

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to