示例#1
0
def list_images(directory):
    ''' 
    Create a list of image tuples sorted by capture timestamp.
    @param directory: directory with JPEG files 
    @return: a list of image tuples with time, directory, lat,long...
    '''
    file_list = []
    for root, sub_folders, files in os.walk(directory):
        file_list += [
            os.path.join(root, filename) for filename in files
            if filename.lower().endswith(".jpg")
        ]

    files = []
    # get GPS data from the images and sort the list by timestamp
    for filepath in file_list:
        metadata = EXIF(filepath)
        try:
            t = metadata.extract_capture_time()
            #lat = metadata["Exif.GPSInfo.GPSLatitude"].value
            #latRef = metadata["Exif.GPSInfo.GPSLatitudeRef"].value
            #lon = metadata["Exif.GPSInfo.GPSLongitude"].value
            #lonRef = metadata["Exif.GPSInfo.GPSLongitudeRef"].value
            geo = metadata.extract_geo()
            direction = metadata.extract_direction()
            files.append(
                (filepath, geo["latitude"], geo["longitude"], direction))
        except KeyError, e:
            # if any of the required tags are not set the image is not added to the list
            print("Skipping {0}: {1}".format(filename, e))
示例#2
0
 def _read_lat_lon(self, filename):
     '''
     Use EXIF class to parse latitude and longitude from EXIF.
     '''
     exif = EXIF(filename)
     lon, lat = exif.extract_lon_lat()
     return lat, lon
示例#3
0
 def _read_direction(self, filename):
     '''
     Use EXIF class to parse compass direction from EXIF.
     '''
     exif = EXIF(filename)
     direction = exif.extract_direction()
     return direction
示例#4
0
 def _read_lat_lon(self, filename):
     '''
     Use EXIF class to parse latitude and longitude from EXIF.
     '''
     exif = EXIF(filename)
     lon, lat = exif.extract_lon_lat()
     return lat, lon
示例#5
0
def list_images(directory):
    """
    Create a list of image tuples sorted by capture timestamp.
    @param directory: directory with JPEG files
    @return: a list of image tuples with time, directory, lat,long...
    """
    file_list = []
    for root, sub_folders, files in os.walk(directory):
        file_list += [os.path.join(root, filename) for filename in files if filename.lower().endswith(".jpg")]

    files = []
    # get DateTimeOriginal data from the images and sort the list by timestamp
    for filepath in file_list:
        metadata = EXIF(filepath)
        try:
            t = metadata.extract_capture_time()
            s = int(t.microsecond / 1000000)
            files.append(Picture_infos(filepath, t, s))
            # print t
            # print type(t)
        except KeyError as e:
            # if any of the required tags are not set the image is not added to the list
            print("Skipping {0}: {1}".format(filepath, e))

    files.sort(key=lambda file: file.DateTimeOriginal)
    # print_list(files)
    return files
示例#6
0
 def _read_direction(self, filename):
     '''
     Use EXIF class to parse compass direction from EXIF.
     '''
     exif = EXIF(filename)
     direction = exif.extract_direction()
     return direction
示例#7
0
def create_mapillary_description(filename,
                                 username,
                                 email,
                                 upload_hash,
                                 sequence_uuid,
                                 interpolated_heading=None,
                                 orientation=1,
                                 verbose=False):
    '''
    Check that image file has the required EXIF fields.

    Incompatible files will be ignored server side.
    '''
    # read exif
    exif = EXIF(filename)

    if not verify_exif(filename):
        return False

    # write the mapillary tag
    mapillary_description = {}
    mapillary_description["MAPLongitude"], mapillary_description[
        "MAPLatitude"] = exif.extract_lon_lat()
    #required date format: 2015_01_14_09_37_01_000
    mapillary_description["MAPCaptureTime"] = datetime.datetime.strftime(
        exif.extract_capture_time(), "%Y_%m_%d_%H_%M_%S_%f")[:-3]
    mapillary_description["MAPOrientation"] = exif.extract_orientation()
    heading = exif.extract_direction()
    if heading is None:
        heading = 0.0
    heading = normalize_bearing(
        interpolated_heading
    ) if interpolated_heading is not None else normalize_bearing(heading)
    mapillary_description["MAPCompassHeading"] = {
        "TrueHeading": heading,
        "MagneticHeading": heading
    }
    mapillary_description["MAPSettingsUploadHash"] = upload_hash
    mapillary_description["MAPSettingsEmail"] = email
    mapillary_description["MAPSettingsUsername"] = username
    settings_upload_hash = hashlib.sha256(
        "%s%s%s" %
        (upload_hash, email, base64.b64encode(filename))).hexdigest()
    mapillary_description['MAPSettingsUploadHash'] = settings_upload_hash
    mapillary_description['MAPPhotoUUID'] = str(uuid.uuid4())
    mapillary_description['MAPSequenceUUID'] = str(sequence_uuid)
    mapillary_description['MAPDeviceModel'] = exif.extract_model()
    mapillary_description['MAPDeviceMake'] = exif.extract_make()

    # write to file
    json_desc = json.dumps(mapillary_description)
    if verbose:
        print "tag: {0}".format(json_desc)
    metadata = ExifEdit(filename)
    metadata.add_image_description(json_desc)
    metadata.add_orientation(orientation)
    metadata.add_direction(heading)
    metadata.write()
示例#8
0
def create_mapillary_description(filename, username, email,
                                 upload_hash, sequence_uuid,
                                 interpolated_heading=None,
                                 orientation=1,
                                 verbose=False):
    '''
    Check that image file has the required EXIF fields.

    Incompatible files will be ignored server side.
    '''
    # read exif
    exif = EXIF(filename)

    if not verify_exif(filename):
        return False

    # write the mapillary tag
    mapillary_description = {}
    mapillary_description["MAPLongitude"], mapillary_description["MAPLatitude"] = exif.extract_lon_lat()
    #required date format: 2015_01_14_09_37_01_000
    mapillary_description["MAPCaptureTime"] = datetime.datetime.strftime(exif.extract_capture_time(), "%Y_%m_%d_%H_%M_%S_%f")[:-3]
    mapillary_description["MAPOrientation"] = exif.extract_orientation()
    heading = exif.extract_direction()
    if heading is None:
        heading = 0.0
    heading = normalize_bearing(interpolated_heading) if interpolated_heading is not None else normalize_bearing(heading)
    mapillary_description["MAPCompassHeading"] = {"TrueHeading": heading, "MagneticHeading": heading}
    mapillary_description["MAPSettingsUploadHash"] = upload_hash
    mapillary_description["MAPSettingsEmail"] = email
    mapillary_description["MAPSettingsUsername"] = username
    settings_upload_hash = hashlib.sha256("%s%s%s" % (upload_hash, email, base64.b64encode(filename))).hexdigest()
    mapillary_description['MAPSettingsUploadHash'] = settings_upload_hash
    mapillary_description['MAPPhotoUUID'] = str(uuid.uuid4())
    mapillary_description['MAPSequenceUUID'] = str(sequence_uuid)
    mapillary_description['MAPDeviceModel'] = exif.extract_model()
    mapillary_description['MAPDeviceMake'] = exif.extract_make()

    # write to file
    json_desc = json.dumps(mapillary_description)
    if verbose:
        print "tag: {0}".format(json_desc)
    metadata = ExifEdit(filename)
    metadata.add_image_description(json_desc)
    metadata.add_orientation(orientation)
    metadata.add_direction(heading)
    metadata.write()
示例#9
0
 def _read_capture_time(self, filename):
     '''
     Use EXIF class to parse capture time from EXIF.
     '''
     exif = EXIF(filename)
     return exif.extract_capture_time()
示例#10
0
    # Handle EXIF errors
    num_missing_date = 0
    num_exif_error = 0
    failed_folder = os.path.join(data_path, "failed")
    io.mkdir_p(failed_folder)
    valid_files = []

    print("\nAdding GPS ...")
    # Add GPS positions
    for i, p in enumerate(meta["photos"]):

        photo_file = p["photo_file_path"]

        if os.path.isfile(photo_file):
            exif = EXIF(photo_file)
            try:
                exif = EXIF(photo_file)
            except Exception as e:
                print "EXIF read error '{}' for image {}. Skipping".format(
                    e, photo_file)
                shutil.move(
                    photo_file,
                    os.path.join(failed_folder, os.path.basename(photo_file)))
                num_exif_error += 1
                continue

            try:
                capture_time = exif.extract_capture_time()
            except Exception as e:
                print "Datetime error '{}' for image {}. Skipping".format(
示例#11
0
        action='store_true',
        dest='backup',
        help='store backup of overwritten values in Mapillary JSON')

    args = parser.parse_args()

    if args.orientation is not None:
        exifOrientation = format_orientation(args.orientation)

    s = Sequence(args.path)
    if args.interpolate:
        bearings = s.interpolate_direction()

    for filename in s.get_file_list(args.path):
        stat = os.stat(filename)
        exifRead = EXIF(filename)
        mapillaryTag = json.loads(exifRead.extract_image_description())

        if args.interpolate:
            bearing = bearings[filename]
        else:
            bearing = exifRead.extract_direction()

        if args.offset:
            bearing = offset_bearing(bearing, args.offset)

        exifEdit = ExifEdit(filename)

        if args.interpolate or args.offset:
            exifEdit.add_direction(bearing, precision=10)
            if (args.backup):
示例#12
0
def exif_time(filename):
    '''
    Get image capture time from exif
    '''
    metadata = EXIF(filename)
    return metadata.extract_capture_time()
    # Handle EXIF errors
    num_missing_date = 0
    num_exif_error = 0
    failed_folder = os.path.join(data_path, "failed")
    io.mkdir_p(failed_folder)
    valid_files = []

    print("\nAdding GPS ...")
    # Add GPS positions
    for i, p in enumerate(meta["photos"]):

        photo_file = p["photo_file_path"]

        if os.path.isfile(photo_file):
            exif = EXIF(photo_file)
            try:
                exif = EXIF(photo_file)
            except Exception as e:
                print "EXIF read error '{}' for image {}. Skipping".format(e, photo_file)
                shutil.move(photo_file, os.path.join(failed_folder, os.path.basename(photo_file)))
                num_exif_error += 1
                continue

            try: 
                capture_time = exif.extract_capture_time()
            except Exception as e:
                print "Datetime error '{}' for image {}. Skipping".format(e, photo_file)
                shutil.move(photo_file, os.path.join(failed_folder, os.path.basename(photo_file)))
                num_exif_error += 1
                continue
    # get the list of images in the folder
    # Caution: all nested folders will be merged into one sequence!
    s = Sequence(path, skip_folders=['success', 'duplicates'], skip_subfolders=skip_subfolders)

    if len(s.file_list) == 0:
        print('No images in the folder or all images have all ready been uploaded to Mapillary')
        print('Note: If upload fails mid-sequence due to connection failure or similar, you should manually push the images to the server at http://www.mapillary.com/map/upload/im/ and pressing "push to Mapillary".')
        sys.exit()

    print("Uploading sequence {0}.".format(sequence_id))

    # check mapillary tag and required exif
    file_list = []
    for filepath in s.file_list:
        mapillary_tag_exists = EXIF(filepath).mapillary_tag_exists()
        if mapillary_tag_exists:
            print("File {} contains Mapillary EXIF tags, use upload.py instead.".format(filepath))

        required_exif_exist = verify_exif(filepath)
        if not required_exif_exist:
            print("File {} missing required exif".format(filepath))

        if required_exif_exist and (not mapillary_tag_exists):
            file_list.append(filepath)

    #upload valid files
    upload_file_list(file_list, params)

    # ask user if finalize upload to check that everything went fine
    print("===\nFinalizing upload will submit all successful uploads and ignore all failed.\nIf all files were marked as successful, everything is fine, just press 'y'.")
示例#15
0
        sys.exit()

    if path.lower().endswith(".jpg"):
        # single file
        file_list = [path]
    else:
        # folder(s)
        file_list = []
        for root, sub_folders, files in os.walk(path):
            file_list += [
                os.path.join(root, filename) for filename in files
                if filename.lower().endswith(".jpg")
            ]

    num_file = len(file_list)
    for i, filepath in enumerate(file_list):
        exif = EXIF(filepath)
        description_ = exif.extract_image_description()
        exif_edit = ExifEdit(filepath)
        try:
            description_ = json.loads(description_)
        except:
            description_ = {}

        if 'MAPSettingsProject' not in description_ or overwrite:
            description_['MAPSettingsProject'] = project_key
            description_ = {}
            exif_edit.add_image_description(description_)
            exif_edit.write()

    print("Done, processed %s files" % len(file_list))
示例#16
0
def create_mapillary_description(filename,
                                 username,
                                 email,
                                 userkey,
                                 upload_hash,
                                 sequence_uuid,
                                 interpolated_heading=None,
                                 offset_angle=0.0,
                                 timestamp=None,
                                 orientation=None,
                                 project="",
                                 secret_hash=None,
                                 external_properties=None,
                                 verbose=False):
    '''
    Check that image file has the required EXIF fields.

    Incompatible files will be ignored server side.
    '''
    # read exif
    exif = EXIF(filename)

    if not verify_exif(filename):
        return False

    if orientation is None:
        orientation = exif.extract_orientation()

    # write the mapillary tag
    mapillary_description = {}
    mapillary_description["MAPLongitude"], mapillary_description[
        "MAPLatitude"] = exif.extract_lon_lat()
    mapillary_description["MAPAltitude"] = exif.extract_altitude()

    # capture time: required date format: 2015_01_14_09_37_01_000
    if timestamp is None:
        timestamp = exif.extract_capture_time()
    mapillary_description["MAPCaptureTime"] = datetime.datetime.strftime(
        timestamp, "%Y_%m_%d_%H_%M_%S_%f")[:-3]
    mapillary_description["MAPOrientation"] = orientation
    heading = exif.extract_direction()

    if heading is None:
        heading = 0.0
    heading = normalize_bearing(
        interpolated_heading + offset_angle
    ) if interpolated_heading is not None else normalize_bearing(heading +
                                                                 offset_angle)
    mapillary_description["MAPCompassHeading"] = {
        "TrueHeading": heading,
        "MagneticHeading": heading
    }

    # authentication
    assert (email is not None or userkey is not None)
    if email is not None:
        mapillary_description["MAPSettingsEmail"] = email
    if username is not None:
        mapillary_description["MAPSettingsUsername"] = username
    if userkey is not None:
        mapillary_description["MAPSettingsUserKey"] = userkey
    if upload_hash is not None:
        settings_upload_hash = hashlib.sha256(
            "%s%s%s" %
            (upload_hash, email, base64.b64encode(filename))).hexdigest()
        mapillary_description['MAPSettingsUploadHash'] = settings_upload_hash

    mapillary_description['MAPPhotoUUID'] = str(uuid.uuid4())
    mapillary_description['MAPSequenceUUID'] = str(sequence_uuid)
    mapillary_description['MAPDeviceModel'] = exif.extract_model()
    mapillary_description['MAPDeviceMake'] = exif.extract_make()
    if upload_hash is None and secret_hash is not None:
        mapillary_description['MAPVideoSecure'] = secret_hash

    mapillary_description["MAPSettingsProject"] = project

    # external properties
    if external_properties is not None:
        mapillary_description['MAPExternalProperties'] = external_properties

    # write to file
    if verbose:
        print("tag: {0}".format(mapillary_description))
    metadata = ExifEdit(filename)
    metadata.add_image_description(mapillary_description)
    metadata.add_orientation(orientation)
    metadata.add_direction(heading)
    metadata.write()
示例#17
0
def create_mapillary_description(filename,
                                 username,
                                 email,
                                 userkey,
                                 upload_hash,
                                 sequence_uuid,
                                 interpolated_heading=None,
                                 offset_angle=0.0,
                                 timestamp=None,
                                 orientation=None,
                                 project="",
                                 secret_hash=None,
                                 external_properties=None,
                                 verbose=False,
                                 make="",
                                 model=""):
    '''
    Check that image file has the required EXIF fields.

    Incompatible files will be ignored server side.
    '''
    # read exif
    exif = EXIF(filename)

    if not verify_exif(filename):
        return False

    if orientation is None:
        orientation = exif.extract_orientation()

    # write the mapillary tag
    mapillary_description = {}

    # lat, lon of the image, takes precedence over EXIF GPS values
    mapillary_description["MAPLongitude"], mapillary_description[
        "MAPLatitude"] = exif.extract_lon_lat()

    # altitude of the image, takes precedence over EXIF GPS values, assumed 0
    # if missing
    mapillary_description["MAPAltitude"] = exif.extract_altitude()

    # capture time: required date format: 2015_01_14_09_37_01_000, TZ MUST be
    # UTC
    if timestamp is None:
        timestamp = exif.extract_capture_time()

    # The capture time of the image in UTC. Will take precedence over any
    # other time tags in the EXIF
    mapillary_description["MAPCaptureTime"] = datetime.datetime.strftime(
        timestamp, "%Y_%m_%d_%H_%M_%S_%f")[:-3]

    # EXIF orientation of the image
    mapillary_description["MAPOrientation"] = orientation
    heading = exif.extract_direction()

    if heading is None:
        heading = 0.0
    heading = normalize_bearing(
        interpolated_heading + offset_angle
    ) if interpolated_heading is not None else normalize_bearing(heading +
                                                                 offset_angle)

    # bearing of the image
    mapillary_description["MAPCompassHeading"] = {
        "TrueHeading": heading,
        "MagneticHeading": heading
    }

    # authentication
    assert (email is not None or userkey is not None)
    if email is not None:
        mapillary_description["MAPSettingsEmail"] = email
    if username is not None:
        mapillary_description["MAPSettingsUsername"] = username

    # use this if available, and omit MAPSettingsUsername and MAPSettingsEmail
    # for privacy reasons
    if userkey is not None:
        mapillary_description["MAPSettingsUserKey"] = userkey
    if upload_hash is not None:
        settings_upload_hash = hashlib.sha256(
            "%s%s%s" %
            (upload_hash, email, base64.b64encode(filename))).hexdigest()
        # this is not checked in the backend right now, will likely be changed to have user_key instead of email as part
        # of the hash
        mapillary_description['MAPSettingsUploadHash'] = settings_upload_hash

    # a unique photo ID to check for duplicates in the backend in case the
    # image gets uploaded more than once
    mapillary_description['MAPPhotoUUID'] = str(uuid.uuid4())
    # a sequene ID to make the images go together (order by MAPCaptureTime)
    mapillary_description['MAPSequenceUUID'] = str(sequence_uuid)

    # The device manufacturer
    if make:
        mapillary_description['MAPDeviceMake'] = make
    else:
        mapillary_description['MAPDeviceMake'] = exif.extract_make()

    # The device model
    if model:
        mapillary_description['MAPDeviceModel'] = model
    else:
        mapillary_description['MAPDeviceModel'] = exif.extract_model()

    if upload_hash is None and secret_hash is not None:
        mapillary_description['MAPVideoSecure'] = secret_hash

    if project:
        mapillary_description["MAPSettingsProject"] = project

    # external properties (optional)
    if external_properties is not None:
        # externl proerties can be saved and searched in Mapillary later on
        mapillary_description['MAPExternalProperties'] = external_properties

    if make:
        mapillary_description['MAPDeviceMake'] = make

    if model:
        mapillary_description['MAPDeviceModel'] = model
    # write to file
    if verbose:
        print("tag: {0}".format(mapillary_description))
    metadata = ExifEdit(filename)
    metadata.add_image_description(mapillary_description)
    metadata.add_orientation(orientation)
    metadata.add_direction(heading)
    metadata.write()
示例#18
0
 def _read_capture_time(self, filename):
     '''
     Use EXIF class to parse capture time from EXIF.
     '''
     exif = EXIF(filename)
     return exif.extract_capture_time()
示例#19
0
def upload_file(filepath,
                url,
                permission,
                signature,
                key=None,
                move_files=True,
                keep_file_names=True):
    '''
    Upload file at filepath.

    Move to subfolders 'success'/'failed' on completion if move_files is True.
    '''
    filename = os.path.basename(filepath)

    if keep_file_names:
        s3_filename = filename
    else:
        try:
            s3_filename = EXIF(filepath).exif_name()
        except:
            s3_filename = filename

    # add S3 'path' if given
    if key is None:
        s3_key = s3_filename
    else:
        s3_key = key + s3_filename

    parameters = {
        "key": s3_key,
        "AWSAccessKeyId": "AKIAI2X3BJAT2W75HILA",
        "acl": "private",
        "policy": permission,
        "signature": signature,
        "Content-Type": "image/jpeg"
    }

    with open(filepath, "rb") as f:
        encoded_string = f.read()

    data, headers = encode_multipart(
        parameters,
        {'file': {
            'filename': filename,
            'content': encoded_string
        }})

    root_path = os.path.dirname(filepath)
    success_path = os.path.join(root_path, 'success')
    failed_path = os.path.join(root_path, 'failed')
    lib.io.mkdir_p(success_path)
    lib.io.mkdir_p(failed_path)

    for attempt in range(MAX_ATTEMPTS):
        try:
            request = urllib2.Request(url, data=data, headers=headers)
            response = urllib2.urlopen(request)

            if response.getcode() == 204:
                if move_files:
                    os.rename(filepath, os.path.join(success_path, filename))
                # print("Success: {0}".format(filename))
            else:
                if move_files:
                    os.rename(filepath, os.path.join(failed_path, filename))
                print("Failed: {0}".format(filename))
            break  # attempts

        except urllib2.HTTPError as e:
            print("HTTP error: {0} on {1}".format(e, filename))
            time.sleep(5)
        except urllib2.URLError as e:
            print("URL error: {0} on {1}".format(e, filename))
            time.sleep(5)
        except OSError as e:
            print("OS error: {0} on {1}".format(e, filename))
            time.sleep(5)
        except socket.timeout as e:
            # Specific timeout handling for Python 2.7
            print("Timeout error: {0} (retrying)".format(filename))
示例#20
0
        0: 1,
        90: 6,
        180: 3,
        270: 8
    } # see http://sylvana.net/jpegcrop/exif_orientation.html

    if args.orientation is not None:
        exifOrientation = orientations[args.orientation]

    s = Sequence(args.path)
    if args.interpolate:
        bearings = s.interpolate_direction()

    for filename in s.get_file_list(args.path):
        stat = os.stat(filename)
        exifRead = EXIF(filename)
        mapillaryTag = json.loads(exifRead.tags['Image ImageDescription'].values)
        # print filename, exifRead.extract_orientation(), mapillaryTag['MAPCameraRotation']

        if args.interpolate:
            bearing = bearings[filename];
        else:
            bearing = exifRead.extract_direction();

        if args.offset:
            bearing = offset_bearing(bearing, args.offset)

        exifEdit = ExifEdit(filename)

        if args.interpolate or args.offset:
            exifEdit.add_direction(bearing, precision=10)