def similarity(im0, im1, numiter=1, order=3, constraints=None, filter_pcorr=0, exponent='inf', reports=None): """ Return similarity transformed image im1 and transformation parameters. Transformation parameters are: isotropic scale factor, rotation angle (in degrees), and translation vector. A similarity transformation is an affine transformation with isotropic scale and without shear. Args: im0 (2D numpy array): The first (template) image im1 (2D numpy array): The second (subject) image numiter (int): How many times to iterate when determining scale and rotation order (int): Order of approximation (when doing transformations). 1 = linear, 3 = cubic etc. filter_pcorr (int): Radius of a spectrum filter for translation detection exponent (float or 'inf'): The exponent value used during processing. Refer to the docs for a thorough explanation. Generally, pass "inf" when feeling conservative. Otherwise, experiment, values below 5 are not even supposed to work. constraints (dict or None): Specify preference of seeked values. Pass None (default) for no constraints, otherwise pass a dict with keys ``angle``, ``scale``, ``tx`` and/or ``ty`` (i.e. you can pass all, some of them or none of them, all is fine). The value of a key is supposed to be a mutable 2-tuple (e.g. a list), where the first value is related to the constraint center and the second one to softness of the constraint (the higher is the number, the more soft a constraint is). More specifically, constraints may be regarded as weights in form of a shifted Gaussian curve. However, for precise meaning of keys and values, see the documentation section :ref:`constraints`. Names of dictionary keys map to names of command-line arguments. Returns: dict: Contains following keys: ``scale``, ``angle``, ``tvec`` (Y, X), ``success`` and ``timg`` (the transformed subject image) .. note:: There are limitations * Scale change must be less than 2. * No subpixel precision (but you can use *resampling* to get around this). """ bgval = utils.get_borderval(im1, 5) res = _similarity(im0, im1, numiter, order, constraints, filter_pcorr, exponent, bgval, reports) im2 = transform_img_dict(im1, res, bgval, order) # Order of mask should be always 1 - higher values produce strange results. imask = transform_img_dict(np.ones_like(im1), res, 0, 1) # This removes some weird artifacts imask[imask > 0.8] = 1.0 # Framing here = just blending the im2 with its BG according to the mask im3 = utils.frame_img(im2, imask, 10) res["timg"] = im3 return res
def similarity(im0, im1, numiter=1, order=3, constraints=None, filter_pcorr=0, exponent='inf'): """ Return similarity transformed image im1 and transformation parameters. Transformation parameters are: isotropic scale factor, rotation angle (in degrees), and translation vector. A similarity transformation is an affine transformation with isotropic scale and without shear. Args: im0 (2D numpy array): The first (template) image im1 (2D numpy array): The second (subject) image numiter (int): How many times to iterate when determining scale and rotation order (int): Order of approximation (when doing transformations). 1 = linear, 3 = cubic etc. filter_pcorr (int): Radius of a spectrum filter for translation detection exponent (float or 'inf'): The exponent value used during processing. Refer to the docs for a thorough explanation. Generally, pass "inf" when feeling conservative. Otherwise, experiment, values below 5 are not even supposed to work. Returns: dict: Contains following keys: ``scale``, ``angle``, ``tvec`` (Y, X), ``success`` and ``timg`` (the transformed subject image) .. note:: There are limitations * Scale change must be less than 2. * No subpixel precision (but you can use *resampling* to get around this). """ shape = im0.shape if shape != im1.shape: raise ValueError("Images must have same shapes.") elif im0.ndim != 2: raise ValueError("Images must be 2-dimensional.") # We are going to iterate and precise scale and angle estimates scale = 1.0 angle = 0.0 im2 = im1 if constraints is None: constraints = dict(angle=[0, None], scale=[1, None]) # During iterations, we have to work with constraints too. # So we make the copy in order to leave the original intact constraints_dynamic = constraints.copy() constraints_dynamic["scale"] = list(constraints["scale"]) constraints_dynamic["angle"] = list(constraints["angle"]) bgval = utils.get_borderval(im1, 5) for ii in range(numiter): newscale, newangle = _get_ang_scale([im0, im2], bgval, exponent, constraints_dynamic) scale *= newscale angle += newangle constraints_dynamic["scale"][0] /= newscale constraints_dynamic["angle"][0] -= newangle im2 = transform_img(im1, scale, angle, bgval=bgval, order=order) # Here we look how is the turn-180 target, stdev = constraints.get("angle", (0, None)) odds = _get_odds(angle, target, stdev) # now we can use pcorr to guess the translation tvec, succ, angle2 = _translation(im0, im2, filter_pcorr, odds, constraints) # The log-polar transform may have got the angle wrong by 180 degrees. # The phase correlation can help us to correct that angle += angle2 angle = utils.wrap_angle(angle, 360) # don't know what it does, but it alters the scale a little bit # scale = (im1.shape[1] - 1) / (int(im1.shape[1] / scale) - 1) Dangle, Dscale = _get_precision(shape, scale) res = dict( scale=scale, angle=angle, tvec=tvec, Dscale=Dscale, Dangle=Dangle, Dt=0.5, success=succ ) im2 = transform_img_dict(im1, res, bgval, order) # Order of mask should be always 1 - higher values produce strange results. imask = transform_img_dict(np.ones_like(im1), res, 0, 1) # This removes some weird artifacts imask[imask > 0.8] = 1.0 # Framing here = just blending the im2 with its BG according to the mask im2 = utils.frame_img(im2, imask, 10) res["timg"] = im2 return res
def similarity(im0, im1, numiter=1, order=3, constraints=None, filter_pcorr=0, exponent='inf'): """ Return similarity transformed image im1 and transformation parameters. Transformation parameters are: isotropic scale factor, rotation angle (in degrees), and translation vector. A similarity transformation is an affine transformation with isotropic scale and without shear. Args: im0 (2D numpy array): The first (template) image im1 (2D numpy array): The second (subject) image numiter (int): How many times to iterate when determining scale and rotation order (int): Order of approximation (when doing transformations). 1 = linear, 3 = cubic etc. filter_pcorr (int): Radius of a spectrum filter for translation detection exponent (float or 'inf'): The exponent value used during processing. Refer to the docs for a thorough explanation. Generally, pass "inf" when feeling conservative. Otherwise, experiment, values below 5 are not even supposed to work. Returns: dict: Contains following keys: ``scale``, ``angle``, ``tvec`` (Y, X), ``success`` and ``timg`` (the transformed subject image) .. note:: There are limitations * Scale change must be less than 2. * No subpixel precision (but you can use *resampling* to get around this). """ shape = im0.shape if shape != im1.shape: raise ValueError("Images must have same shapes.") elif im0.ndim != 2: raise ValueError("Images must be 2-dimensional.") # We are going to iterate and precise scale and angle estimates scale = 1.0 angle = 0.0 im2 = im1 if constraints is None: constraints = dict(angle=[0, None], scale=[1, None]) # During iterations, we have to work with constraints too. # So we make the copy in order to leave the original intact constraints_dynamic = constraints.copy() constraints_dynamic["scale"] = list(constraints["scale"]) constraints_dynamic["angle"] = list(constraints["angle"]) bgval = utils.get_borderval(im1, 5) for ii in range(numiter): newscale, newangle = _get_ang_scale([im0, im2], bgval, exponent, constraints_dynamic) scale *= newscale angle += newangle constraints_dynamic["scale"][0] /= newscale constraints_dynamic["angle"][0] -= newangle im2 = transform_img(im1, scale, angle, bgval=bgval, order=order) # Here we look how is the turn-180 target, stdev = constraints.get("angle", (0, None)) odds = _get_odds(angle, target, stdev) # now we can use pcorr to guess the translation tvec, succ, angle2 = _translation(im0, im2, filter_pcorr, odds, constraints) # The log-polar transform may have got the angle wrong by 180 degrees. # The phase correlation can help us to correct that angle += angle2 angle = utils.wrap_angle(angle, 360) # don't know what it does, but it alters the scale a little bit # scale = (im1.shape[1] - 1) / (int(im1.shape[1] / scale) - 1) Dangle, Dscale = _get_precision(shape, scale) res = dict(scale=scale, angle=angle, tvec=tvec, Dscale=Dscale, Dangle=Dangle, Dt=0.5, success=succ) im2 = transform_img_dict(im1, res, bgval, order) # Order of mask should be always 1 - higher values produce strange results. imask = transform_img_dict(np.ones_like(im1), res, 0, 1) # This removes some weird artifacts imask[imask > 0.8] = 1.0 # Framing here = just blending the im2 with its BG according to the mask im2 = utils.frame_img(im2, imask, 10) res["timg"] = im2 return res