Exemple #1
0
def testXmlFormatException():
    try:
        lensfun.Database(xml='garbage')
    except lensfun.XMLFormatError:
        pass
    else:
        assert False
Exemple #2
0
def testModifier():
    db = lensfun.Database()
    cam = db.find_cameras(cam_maker, cam_model)[0]
    lens = db.find_lenses(cam, lens_maker, lens_model)[0]

    focal_length = 28.0
    aperture = 1.4
    distance = 10
    width = 4256
    height = 2832

    mod = lensfun.Modifier(lens, cam.crop_factor, width, height)
    mod.initialize(focal_length, aperture, distance)

    undistCoords = mod.apply_geometry_distortion()
    assert undistCoords.shape[0] == height and undistCoords.shape[1] == width

    # check if coordinates were actually transformed
    y, x = np.mgrid[0:undistCoords.shape[0], 0:undistCoords.shape[1]]
    coords = np.dstack((x, y))
    assert np.any(undistCoords != coords)

    undistCoords = mod.apply_subpixel_distortion()
    assert undistCoords.shape[0] == height and undistCoords.shape[1] == width
    assert np.any(undistCoords[:, :, 0] != coords)

    undistCoords = mod.apply_subpixel_geometry_distortion()
    assert undistCoords.shape[0] == height and undistCoords.shape[1] == width
    assert np.any(undistCoords[:, :, 0] != coords)
Exemple #3
0
def correct_photo(photo):
    '''Apply distortion correction'''

    #exif = get_exif_data(photo)
    #exif.get('Make')
    #exif.get('Model')

    #https://pypi.python.org/pypi/lensfunpy/0.12.0
    cam_maker = "GoPro"
    cam_model = "HD2"
    #lens="HD2 & Compatibles"

    #Set output filename
    fileName, fileExtension = os.path.splitext(photo)
    undistortedImagePath = "".join([fileName, "_fixN", fileExtension])

    #Query the Lensfun db for camera parameters
    db = lensfunpy.Database()
    cam = db.find_cameras(cam_maker, cam_model)[0]
    lens = db.find_lenses(cam)[0]

    #TODO: set camera parameters from exif data and lensfun
    focalLength = lens.min_focal  #2.5
    aperture = 2.8
    distance = 0

    im = cv2.imread(photo)
    height, width = im.shape[0], im.shape[1]

    mod = lensfunpy.Modifier(lens, cam.crop_factor, width, height)
    mod.initialize(focalLength, aperture, distance)

    undistCoords = mod.apply_geometry_distortion()
    #imUndistorted = cv2.remap(im, undistCoords, None, cv2.INTER_LANCZOS4)
    imUndistorted = cv2.remap(im, undistCoords, None, cv2.INTER_NEAREST)
    #cv2.imwrite(undistortedImagePath, imUndistorted,[int(cv2.IMWRITE_JPEG_QUALITY), 95])

    #Change the order of colors to RGB for Pil (Pillow)
    cvRgbImage = cv2.cvtColor(imUndistorted, cv2.COLOR_BGR2RGB)
    pil_im = Image.fromarray(cvRgbImage)

    #update the metadata for the new files
    exif_dict = piexif.load(photo)
    #exif_dict = piexif.load(pil_im.info["exif"])

    exif_dict["0th"][piexif.ImageIFD.Model] = "HD2 U"
    exif_dict["0th"][piexif.ImageIFD.Make] = "GoPro"
    exif_dict["Exif"][piexif.ExifIFD.FocalLength] = (250, 100)
    #it's actually 21.5 but exif barfs on float
    exif_dict["Exif"][piexif.ExifIFD.FocalLengthIn35mmFilm] = 21
    exif_bytes = piexif.dump(exif_dict)

    #Write the file with metadata, 100% or 95%
    pil_im.save(undistortedImagePath, "jpeg", quality=100, exif=exif_bytes)
Exemple #4
0
def get_map_coords(path, distance=10):
    """Initialize a Lensfun modifier with a subject distance (in meters)
    and return its geometry map for undoing distortion."""
    db = lensfunpy.Database()
    mod = get_modifier(path, db)

    focal_length = float(get_exif('FocalLength', path, numeric=True))
    aperture = float(get_exif('Aperture', path, numeric=True))

    mod.initialize(focal_length, aperture, distance)
    return mod.apply_geometry_distortion()
Exemple #5
0
def testNewLensType():
    # https://github.com/letmaik/lensfunpy/issues/10
    # lensfun added new lens types which were not supported yet by lensfunpy.
    # This test accesses one such lens type and was raising an exception previously.
    db = lensfun.Database()
    cam = db.find_cameras('NIKON CORPORATION', 'NIKON D3S')[0]
    lenses = db.find_lenses(cam, 'Sigma', 'Sigma 8mm f/3.5 EX DG circular fisheye')
    if lenses: # newer lens, only run test if lens actually exists
        assert_equal(lenses[0].type, lensfun.LensType.FISHEYE_EQUISOLID)
    else:
        print('Skipping testNewLensType as lens not found')
Exemple #6
0
def lens_correction(image_to_lens_correct):
    height, width = image_to_lens_correct.shape[
        0], image_to_lens_correct.shape[1]
    db = lensfunpy.Database()
    cam = db.find_cameras(cam_maker, cam_model)[0]
    lens = db.find_lenses(cam, lens_maker, lens_model)[0]
    mod = lensfunpy.Modifier(lens, cam.crop_factor, width, height)
    mod.initialize(focal_length, apperture, 1)
    undist_coords = mod.apply_geometry_distortion()
    grey_image_undistorted = cv2.remap(image_to_lens_correct, undist_coords,
                                       None, cv2.INTER_LANCZOS4)
    return grey_image_undistorted
Exemple #7
0
def testDeallocationBug():
    db = lensfun.Database()
    cam = db.find_cameras(cam_maker, cam_model)[0]
    lens = db.find_lenses(cam, lens_maker, lens_model)[0]

    # By garbage collecting the database object, its queried objects
    # were deallocated as well, which is not what we want.
    # Now, all queried objects hold a reference to the Database object
    # they came from. This way, the Database object is only deallocated
    # when all queried objects were garbage collected.
    del db
    gc.collect()

    assert_equal(cam.maker.lower(), cam_maker.lower())
    assert_equal(lens.maker.lower(), lens_maker.lower())
Exemple #8
0
def getLensfunModifierFromParams(model, params, width, height):
    """
    
    :param str model: 'ptlens', 'poly3', or 'poly5'
    :param list params: a list of 1, 2 or 3 parameters, depending on the model
    :param width: image width in pixels
    :param height: image height in pixels
    """
    xml = lensfunXML(model, *params)
    db = lensfunpy.Database(xml=xml, load_common=False)
    cam = db.cameras[0]
    lens = db.lenses[0]
    mod = lensfunpy.Modifier(lens, cam.crop_factor, width, height)
    mod.initialize(1, 1)
    return mod
Exemple #9
0
def testDatabaseXMLLoading():
    xml = """
<lensdatabase>
    <mount>
        <name>Nikon F AF</name>
        <compat>Nikon F</compat>
        <compat>Nikon F AI</compat>
        <compat>Nikon F AI-S</compat>
        <compat>M42</compat>
        <compat>T2</compat>
        <compat>Generic</compat>
    </mount>
    <camera>
        <maker>Nikon Corporation</maker>
        <maker lang="en">Nikon</maker>
        <model>Nikon D3S</model>
        <model lang="en">D3S</model>
        <mount>Nikon F AF</mount>
        <cropfactor>1.0</cropfactor>
    </camera>
    <lens>
        <maker>Nikon</maker>
        <model>Nikon AI-S Nikkor 28mm f/2.8</model>
        <model lang="en">Nikkor AI-S 28mm f/2.8</model>
        <mount>Nikon F AI-S</mount>
        <cropfactor>1</cropfactor>
        <calibration>
            <!-- Taken with Nikon D600 -->
            <distortion model="ptlens" focal="28" a="0.00929" b="-0.02155" c="0.0021"/>
            <tca model="poly3" focal="28" br="-0.0002306" vr="1.0006860" bb="0.0002350" vb="0.9995614"/>
        </calibration>
    </lens>
</lensdatabase>
    """
    db = lensfun.Database(xml=xml, load_common=False, load_bundled=False)

    assert_equal(len(db.cameras), 1)
    assert_equal(len(db.lenses), 1)
    assert_equal(len(db.mounts), 1)

    cam = db.find_cameras(cam_maker, cam_model)[0]
    lens = db.find_lenses(cam, lens_maker, lens_model)[0]

    assert_equal(cam.maker.lower(), cam_maker.lower())
    assert_equal(cam.model.lower(), cam_model.lower())
    assert_equal(lens.maker.lower(), lens_maker.lower())
    assert_equal(lens.model.lower(), lens_model.lower())
Exemple #10
0
def _lensfun(filename):
    """Use the EXIF data an image calculate lens distortion corrections using the lensfun database

    Args:
        filename(str): The filename to open and extract EXIF data from.

    Returns:
        numpy.ndarray: A map suitable for use with cv2.remap()

    Raises:
        ValueError: The distortion corrections could not be calculated.
    """

    exif = _exif(filename)

    if exif is None:
        raise ValueError('Unable to load EXIF data from {0}'.format(filename))

    # open the lensfun db
    db = lensfunpy.Database()

    # see if our make/model is in the DB
    try:
        cam = db.find_cameras(exif['Make'], exif['Model'])[0]
        lens = db.find_lenses(cam)[0]
    except IndexError:
        raise ValueError('Unable to find a Lensfun entry for {0} {1}'.format(
            exif['Make'], exif['Model']))

    # calculate the distortion corrections
    try:
        focal_length = float(exif['FocalLengthIn35mmFilm'])
        aperture = float(Fraction(*exif['FNumber']))
        distance = int(exif['SubjectDistanceRange'])
    except KeyError as exc:
        raise ValueError(
            'Unable to calculate lens distortion: EXIF data is missing item {0}'
            .format(exc))

    mod = lensfunpy.Modifier(lens, cam.crop_factor, exif['ExifImageWidth'],
                             exif['ExifImageHeight'])

    mod.initialize(focal_length, aperture, distance)

    return mod.apply_geometry_distortion()
Exemple #11
0
def testDatabaseLoading():
    db = lensfun.Database()

    cams = db.find_cameras(cam_maker, cam_model)
    print(cams)
    assert_equal(len(cams), 1)
    cam = cams[0]
    assert_equal(cam.maker.lower(), cam_maker.lower())
    assert_equal(cam.model.lower(), cam_model.lower())
    assert len(str(cam)) > 0

    lenses = db.find_lenses(cam, lens_maker, lens_model)
    assert_equal(len(lenses), 1)
    lens = lenses[0]
    assert_equal(lens.maker.lower(), lens_maker.lower())
    assert len(str(lens)) > 0

    assert_equal(lens.model.lower(), lens_model.lower())
Exemple #12
0
def testDatabaseXMLLoading():
    xml = """
<lensdatabase>
    <mount>
        <name>Nikon F AF</name>
        <compat>Nikon F</compat>
        <compat>Nikon F AI</compat>
        <compat>Nikon F AI-S</compat>
        <compat>M42</compat>
        <compat>T2</compat>
        <compat>Generic</compat>
    </mount>
    <camera>
        <maker>Nikon Corporation</maker>
        <maker lang="en">Nikon</maker>
        <model>Nikon D3S</model>
        <model lang="en">D3S</model>
        <mount>Nikon F AF</mount>
        <cropfactor>1.0</cropfactor>
    </camera>
    <lens>
        <maker>Nikon</maker>
        <model>Nikkor 28mm f/2.8D AF</model>
        <mount>Nikon F AF</mount>
        <cropfactor>1.0</cropfactor>
        <calibration>
            <distortion model="ptlens" focal="28" a="0" b="0.025773" c="-0.085777" />
        </calibration>
    </lens>
</lensdatabase>
    """
    db = lensfun.Database(xml=xml, load_common=False, load_bundled=False)

    assert_equal(len(db.cameras), 1)
    assert_equal(len(db.lenses), 1)
    assert_equal(len(db.mounts), 1)

    cam = db.find_cameras(cam_maker, cam_model)[0]
    lens = db.find_lenses(cam, lens_maker, lens_model)[0]

    assert_equal(cam.maker.lower(), cam_maker.lower())
    assert_equal(cam.model.lower(), cam_model.lower())
    assert_equal(lens.maker.lower(), lens_maker.lower())
    assert_equal(lens.model.lower(), lens_model.lower())
def unskew(image_path, old):
    cam_maker = config["camera_maker"]
    cam_model = config["camera_model"]

    lens_maker = config["lens_maker"]
    lens_model = config["lens_model"]

    # TODO: this would have to be removed...
    if old:
        cam_model = 'Nikon D3300'
        lens_model = "Nikon AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G VR"

    db = lensfunpy.Database()

    try:
        cam = db.find_cameras(cam_maker, cam_model)[0]
    except Exception:
        raise (Exception("Camera not found!"))
    try:
        lens = db.find_lenses(cam, lens_maker, lens_model)[0]
    except Exception:
        raise (Exception("Lens not found!"))

    #  focal_length = lens.min_focal

    # TODO: read from exif

    focal_length = 30
    aperture = 4.2

    # TODO: what's the unit here?
    distance = 10

    im = cv2.imread(image_path)
    height, width = im.shape[0], im.shape[1]

    mod = lensfunpy.Modifier(lens, cam.crop_factor, width, height)
    mod.initialize(focal_length, aperture, distance)

    undist_coords = mod.apply_geometry_distortion()
    unskewed = cv2.remap(im, undist_coords, None, cv2.INTER_LANCZOS4)
    return unskewed
Exemple #14
0
def testDatabaseLoading():
    db = lensfun.Database()

    cams = db.find_cameras(cam_maker, cam_model)
    assert_equal(len(cams), 1)
    cam = cams[0]
    assert_equal(cam.maker.lower(), cam_maker.lower())
    assert_equal(cam.model.lower(), cam_model.lower())
    assert len(str(cam)) > 0

    lenses = db.find_lenses(cam, lens_maker, lens_model)
    assert_equal(len(lenses), 1)
    lens = lenses[0]
    assert_equal(lens.maker.lower(), lens_maker.lower())
    assert len(str(lens)) > 0

    if lensfun.lensfun_version >= (0, 3):
        # lens names were "streamlined" in lensfun 0.3
        assert_equal(lens.model.lower(), u'nikon af nikkor 28mm f/2.8d')
    else:
        assert_equal(lens.model.lower(), lens_model.lower())
Exemple #15
0
def testVignettingCorrection():
    cam_maker = 'NIKON CORPORATION'
    cam_model = 'NIKON D3S'
    lens_maker = 'Nikon'
    lens_model = 'Nikkor AF 20mm f/2.8D'
    focal_length = 20
    aperture = 4
    distance = 10
    width = 4256
    height = 2832

    db = lensfun.Database()
    cam = db.find_cameras(cam_maker, cam_model)[0]
    lens = db.find_lenses(cam, lens_maker, lens_model)[0]

    mod = lensfun.Modifier(lens, cam.crop_factor, width, height)
    mod.initialize(focal_length, aperture, distance)

    img = np.zeros((height, width, 3), np.uint8)
    img[:] = 127
    mod.apply_color_modification(img)
    assert img.mean() > 127
Exemple #16
0
import lensfunpy

cam_maker = 'Canon'
cam_model = 'Canon EOS Rebel T5'
mount = 'T-mount'
lens_maker = 'Canon'
lens_model = 'EFS 18-55mm Image Stabilizer'

db = lensfunpy.Database()

cam = db.find_cameras(cam_maker, cam_model)[0]
lens = db.find_lenses(cam, lens_maker, lens_model, loose_search=True)

print(cam)
print(db.find_mount(cam.mount).compat)

print(lens)
def list_lenses():
    database = lensfunpy.Database()
    for lense in database.lenses:
        lense_string = "Maker: %s \t Model: %s" % (lense.maker, lense.model)
        click.echo(lense_string)
def list_cameras():
    database = lensfunpy.Database()
    for camera in database.cameras:
        camera_string = "Maker: %s \t Model: %s" % (camera.maker, camera.model)
        click.echo(camera_string)
Exemple #19
0
def findCameraAndLensFromExif(tags,
                              lensfunDbObj=None,
                              minAcceptedScore=MIN_ACCEPTED_SCORE,
                              raiseIfNotFoundInDB=True):
    '''
    Note that as of lensfun 0.3.0 lens names are synced to exiv2's naming scheme.
    Before that, exiftool's scheme was used. In general the correct lens will still be found
    in either case with the default minimum score of 85 which is used here.
    '''
    if not tags.get('Composite:LensID'):
        raise LensNotFoundInEXIFError('No LensID in EXIF data')

    if not tags.get('EXIF:Make') or not tags.get('EXIF:Model'):
        raise CameraNotFoundInEXIFError('No camera make/model in EXIF data')

    if lensfunDbObj is None:
        db = lensfunpy.Database()
    else:
        db = lensfunDbObj

    cams = db.find_cameras(tags['EXIF:Make'],
                           tags['EXIF:Model'],
                           loose_search=False)
    if not cams:
        if raiseIfNotFoundInDB:
            raise CameraNotFoundInDBError('Camera "' + tags['EXIF:Make'] +
                                          ' - ' + tags['EXIF:Model'] +
                                          '" not found in DB!')
        else:
            return None, None
    # FIXME cam score is always 0


#    if cams[0].score < minAcceptedScore:
#        raise CameraNotFoundInDBError('Camera "' + tags['EXIF:Make'] + ' - ' + tags['EXIF:Model'] + '" not found! ' +
#                                  'Closest was "' + cams[0].maker + ' - ' + cams[0].model + '" with score ' +
#                                  str(cams[0].score) + ' (<' + str(minAcceptedScore) + ')' )
    cam = cams[0]

    lenses = db.find_lenses(cam,
                            None,
                            tags['Composite:LensID'],
                            loose_search=True)
    if not lenses or lenses[0].score < minAcceptedScore:
        if raiseIfNotFoundInDB:
            if not lenses:
                raise LensNotFoundInDBError('Lens "' +
                                            tags['Composite:LensID'] +
                                            '" not found in DB!')
            if lenses[0].score < minAcceptedScore:
                raise LensNotFoundInDBError('Lens "' +
                                            tags['Composite:LensID'] +
                                            '" not found in DB! ' +
                                            'Closest was "' + lenses[0].model +
                                            '" with score ' +
                                            str(lenses[0].score) + ' (<' +
                                            str(minAcceptedScore) + ')')
        else:
            return cam, None

    lens = lenses[0]
    if lens.model != tags['Composite:LensID']:
        print('NOTE: Using lensfun lens "' + lens.model + '" with score ' + str(lens.score) + \
              ' (EXIF: "' + tags['Composite:LensID'] + '")')

    return cam, lens
Exemple #20
0
 def __init__(self, parent=None, equipmentDict={}, *args):
     super(eqRead, self).__init__()
     self.parent = parent
     self.equipmentDict = equipmentDict
     self.db = lensfunpy.Database(
         paths=glob.glob('libs/lensfunpy-db/*.xml'))