Beispiel #1
0
def test_circle_model_residuals():
    model = CircleModel()
    model.params = (0, 0, 5)
    assert_almost_equal(abs(model.residuals(np.array([[5, 0]]))), 0)
    assert_almost_equal(abs(model.residuals(np.array([[6, 6]]))),
                        np.sqrt(2 * 6**2) - 5)
    assert_almost_equal(abs(model.residuals(np.array([[10, 0]]))), 5)
Beispiel #2
0
def test_circle_model_residuals():
    model = CircleModel()
    model.params = (0, 0, 5)
    assert_almost_equal(abs(model.residuals(np.array([[5, 0]]))), 0)
    assert_almost_equal(abs(model.residuals(np.array([[6, 6]]))),
                        np.sqrt(2 * 6**2) - 5)
    assert_almost_equal(abs(model.residuals(np.array([[10, 0]]))), 5)
Beispiel #3
0
class RadiusEstimator(RadialFinder):
    '''Estimate vessel radius by fitting a circle'''
    def __init__(self, img, threshold=0.2):
        # The main idea of the algo is based on assumed radiual "symmetry"
        # of the result. So when we fit the circle we don't want to work with
        # all the pixels by just the "rim" ones for each angle
        super(RadiusEstimator, self).__init__(
            f=lambda x: x,
            # For each ray, how do you find a rim?
            reduction=lambda x: reduce_last(x, threshold * np.max(x)),
            img=img)
        # And we will be fitting a circle
        self.model = CircleModel()

    def __call__(self, img):
        '''Estimate for the given image'''
        x_, y_ = self.collect(img)

        ii, = np.where(
            np.logical_and(np.logical_and(x_ > 10, x_ < 80),
                           np.logical_and(y_ > 10, y_ < 80)))

        x_, y_ = x_[ii], y_[ii]
        self.model.estimate(np.c_[x_, y_])
        # Give back the circle parameters
        return self.model.params
Beispiel #4
0
def test_circle_model_predict():
    model = CircleModel()
    r = 5
    model.params = (0, 0, r)
    t = np.arange(0, 2 * np.pi, np.pi / 2)

    xy = np.array(((5, 0), (0, 5), (-5, 0), (0, -5)))
    assert_almost_equal(xy, model.predict_xy(t))
Beispiel #5
0
def test_circle_model_int_overflow():
    xy = np.array([[1, 0], [0, 1], [-1, 0], [0, -1]], dtype=np.int32)
    xy += 500

    model = CircleModel()
    model.estimate(xy)

    assert_almost_equal(model.params, [500, 500, 1])
Beispiel #6
0
def test_circle_model_predict():
    model = CircleModel()
    r = 5
    model.params = (0, 0, r)
    t = np.arange(0, 2 * np.pi, np.pi / 2)

    xy = np.array(((5, 0), (0, 5), (-5, 0), (0, -5)))
    assert_almost_equal(xy, model.predict_xy(t))
Beispiel #7
0
 def __init__(self, img, threshold=0.2):
     # The main idea of the algo is based on assumed radiual "symmetry"
     # of the result. So when we fit the circle we don't want to work with
     # all the pixels by just the "rim" ones for each angle
     super(RadiusEstimator, self).__init__(
         f=lambda x: x,
         # For each ray, how do you find a rim?
         reduction=lambda x: reduce_last(x, threshold * np.max(x)),
         img=img)
     # And we will be fitting a circle
     self.model = CircleModel()
Beispiel #8
0
def test_circle_model_insufficient_data():
    model = CircleModel()

    with expected_warnings(["Input data does not contain enough significant"]):
        model.estimate(np.array([[1, 2], [3, 4]]))

    with expected_warnings(["Input data does not contain enough significant"]):
        model.estimate(np.ones((6, 2)))

    with expected_warnings(["Input data does not contain enough significant"]):
        model.estimate(np.array([[0, 0], [1, 1], [2, 2]]))
Beispiel #9
0
    def fit(self, image):
        B = image > 0.5 * np.max(image)  #+3*np.std(image)

        circle = CircleModel()
        # Need a better model here
        hull = array_convex_hull(B)
        x_, y_ = hull.T
        x_ = np.r_[x_, x_[0]]
        y_ = np.r_[y_, y_[0]]
        circle.estimate(np.c_[x_, y_])

        # Plot ellipse
        XC, YC, R = circle.params
        x = XC + R * np.sin(self.thetas)
        y = YC + R * np.cos(self.thetas)

        self.params = (XC, YC, R)

        return B, np.c_[x, y]
Beispiel #10
0
def test_ransac_shape():
    # generate original data without noise
    model0 = CircleModel()
    model0.params = (10, 12, 3)
    t = np.linspace(0, 2 * np.pi, 1000)
    data0 = model0.predict_xy(t)

    # add some faulty data
    outliers = (10, 30, 200)
    data0[outliers[0], :] = (1000, 1000)
    data0[outliers[1], :] = (-50, 50)
    data0[outliers[2], :] = (-100, -10)

    # estimate parameters of corrupted data
    model_est, inliers = ransac(data0, CircleModel, 3, 5, random_state=1)

    # test whether estimated parameters equal original parameters
    assert_almost_equal(model0.params, model_est.params)
    for outlier in outliers:
        assert outlier not in inliers
Beispiel #11
0
def test_ransac_shape():
    # generate original data without noise
    model0 = CircleModel()
    model0.params = (10, 12, 3)
    t = np.linspace(0, 2 * np.pi, 1000)
    data0 = model0.predict_xy(t)

    # add some faulty data
    outliers = (10, 30, 200)
    data0[outliers[0], :] = (1000, 1000)
    data0[outliers[1], :] = (-50, 50)
    data0[outliers[2], :] = (-100, -10)

    # estimate parameters of corrupted data
    model_est, inliers = ransac(data0, CircleModel, 3, 5,
                                random_state=1)

    # test whether estimated parameters equal original parameters
    assert_equal(model0.params, model_est.params)
    for outlier in outliers:
        assert outlier not in inliers
Beispiel #12
0
    def fit(self, image):
        B = np.zeros_like(image)
        # Radial sample for maximum
        x_, y_ = self.m.collect(image)
        # We are only after points that are not too far
        ii, = np.where(
            np.logical_and(np.logical_and(x_ > 10, x_ < 80),
                           np.logical_and(y_ > 10, y_ < 80)))
        x_ = x_[ii]
        y_ = y_[ii]
        B[x_, y_] = 1

        circle = CircleModel()
        circle.estimate(np.c_[x_, y_])

        XC, YC, R = circle.params
        x = XC + R * np.sin(self.thetas)
        y = YC + R * np.cos(self.thetas)

        self.params = (XC, YC, R)

        return B, np.c_[x, y]
Beispiel #13
0
def test_circle_model_estimate():
    # generate original data without noise
    model0 = CircleModel()
    model0.params = (10, 12, 3)
    t = np.linspace(0, 2 * np.pi, 1000)
    data0 = model0.predict_xy(t)

    # add gaussian noise to data
    random_state = np.random.RandomState(1234)
    data = data0 + random_state.normal(size=data0.shape)

    # estimate parameters of noisy data
    model_est = CircleModel()
    model_est.estimate(data)

    # test whether estimated parameters almost equal original parameters
    assert_almost_equal(model0.params, model_est.params, 0)
Beispiel #14
0
def test_circle_model_estimate():
    # generate original data without noise
    model0 = CircleModel()
    model0.params = (10, 12, 3)
    t = np.linspace(0, 2 * np.pi, 1000)
    data0 = model0.predict_xy(t)

    # add gaussian noise to data
    random_state = np.random.RandomState(1234)
    data = data0 + random_state.normal(size=data0.shape)

    # estimate parameters of noisy data
    model_est = CircleModel()
    model_est.estimate(data)

    # test whether estimated parameters almost equal original parameters
    assert_almost_equal(model0.params, model_est.params, 1)
Beispiel #15
0
def fit_objects(image, fit_obj='circle'):
    """Fits objects in each region of the input image, returning the
    parameters of each object.

    Parameters
    ----------
    image : (N, M) ndarray
        Binary input image.
    fit_obj : string, optional (default : 'circle')
        Object to be fitted on the regions. Accepts the strings 'circle'
        and 'ellipse'.

    Returns
    -------
    image_fit : (N, M, 3) ndarray
        An image with objects in green representing the fitted objects
        labeling each region.
    data_fit : array
        The parameters for each object fitted. Each row corresponds to
        a region present on the input image. Each column represents one
        parameter of the fitted object. For fit_obj='circle', they are
        the coordinates for the center of the circle, and the radius
        (x_center, y_center, radius); for fit_obj='ellipse', they are
        the coordinates for the center of the ellipse, the major and
        minor axis and the orientation (x_center, y_center, minor_axis,
        major_axis, theta).

    Examples
    --------
    >>> from skcv.draw import draw_synthetic_circles
    >>> from skimage import img_as_bool
    >>> image = draw_synthetic_circles((512, 512), quant=20, shades=1,
                                       seed=0)
    >>> image_fit, data_fit = fit_objects(img_as_bool(image),
                                          fit_obj='circle')

    >>> from skcv.draw import draw_synthetic_ellipses
    >>> from skimage import img_as_bool
    >>> image = draw_synthetic_ellipses((512, 512), quant=20, shades=1,
                                        seed=0)
    >>> image_fit, data_fit = fit_objects(img_as_bool(image),
                                          fit_obj='ellipse')
    """

    image_fit = gray2rgb(image)

    # checking labels.
    img_label, num_objects = label(image, return_num=True)

    if fit_obj == 'circle':
        obj = CircleModel()
        data_fit = np.zeros((num_objects, 3))
    elif fit_obj == 'ellipse':
        obj = EllipseModel()
        data_fit = np.zeros((num_objects, 5))

    for num in range(num_objects):
        # finding the contour.
        obj_contour = find_contours(img_label == num+1,
                                    fully_connected='high',
                                    level=0)

        try:
            # modelling image using obtained points.
            obj.estimate(obj_contour[0])
            data_fit[num] = obj.params
            aux_fit = data_fit[num].astype(int)

            if fit_obj == 'circle':
                # drawing circle.
                rows, cols = circle(aux_fit[0], aux_fit[1], aux_fit[2],
                                    shape=image_fit.shape)
                image_fit[rows, cols] = [False, True, False]
            elif fit_obj == 'ellipse':
                # drawing ellipse.
                rows, cols = ellipse_perimeter(aux_fit[0], aux_fit[1],
                                               aux_fit[2], aux_fit[3],
                                               aux_fit[4],
                                               shape=image_fit.shape)
                image_fit[rows, cols] = [False, True, False]
        except TypeError:
            print('No sufficient points on region #', num)

    return image_fit, data_fit
hsv = rgb2hsv(small)

deviations = []
for color in (0, 1, 2):
    masked = ma.array(hsv[:, :, color], mask=~canvas.astype(np.bool))
    deviations.append(masked.std())

mole.h = deviations[0]
mole.s = deviations[1]
mole.v = deviations[2]

# In[104]:

from skimage.measure import CircleModel

circle_model = CircleModel()
circle_model.estimate(contours[0])
symmetry = circle_model.residuals(contours[0]).mean()

mole.symmetry = symmetry

# In[125]:

diameter = (19.05 / coin_radius) * (circle_model.params[2])

mole.diameter = diameter

mole.status = 100

db.session.merge(mole)
db.session.commit()
Beispiel #17
0
def test_circle_model_invalid_input():
    with testing.raises(ValueError):
        CircleModel().estimate(np.empty((5, 3)))
Beispiel #18
0
        max_ = np.argmax(vals)
        first = (i[:c][max_], j[:c][max_], vals[max_])

        vals = line_values[c:]
        max_ = np.argmax(vals)
        second = (i[c:][max_], j[c:][max_], vals[max_])

        return first, second


# --------------------------------------------------------------------

if __name__ == '__main__':
    from skimage.measure import EllipseModel, CircleModel

    ellipse, circle = EllipseModel(), CircleModel()

    from filters import normalize
    import matplotlib
    #matplotlib.use('AGG')
    import matplotlib.pyplot as plt

    import skimage.io as io

    rpath = '/home/mirok/Downloads/MIRO_TSeries-01302019-0918-028_cycle_001_ch02_short_video-1.tif'
    red_seq = io.imread(rpath)

    red_nseq = normalize(red_seq)

    gpath = '/home/mirok/Downloads/MIRO_TSeries-01302019-0918-028_cycle_001_ch01_short_video-1.tif'
    green_seq = io.imread(gpath)
Beispiel #19
0
def grid_field_props(
        A, maxima='centroid',  allProps=True,
        **kwargs):
    """
    Extracts various measures from a spatial autocorrelogram

    Parameters
    ----------
    A : array_like
        The spatial autocorrelogram (SAC)
    maxima : str, optional
        The method used to detect the peaks in the SAC.
        Legal values are 'single' and 'centroid'. Default 'centroid'
    allProps : bool, optional
        Whether to return a dictionary that contains the attempt to fit an
        ellipse around the edges of the central size peaks. See below
        Default True

    Returns
    -------
    props : dict
        A dictionary containing measures of the SAC. Keys include:
        * gridness score
        * scale
        * orientation
        * coordinates of the peaks (nominally 6) closest to SAC centre
        * a binary mask around the extent of the 6 central fields
        * values of the rotation procedure used to calculate gridness
        * ellipse axes and angle (if allProps is True and the it worked)

    Notes
    -----
    The output from this method can be used as input to the show() method
    of this class.
    When it is the plot produced will display a lot more informative.

    See Also
    --------
    ephysiopy.common.binning.autoCorr2D()

    """
    A_tmp = A.copy()
    A_tmp[~np.isfinite(A)] = -1
    A_tmp[A_tmp <= 0] = -1
    A_sz = np.array(np.shape(A))
    # [STAGE 1] find peaks & identify 7 closest to centre
    if 'min_distance' in kwargs:
        min_distance = kwargs.pop('min_distance')
    else:
        min_distance = np.ceil(np.min(A_sz / 2) / 8.).astype(int)
    
    peak_idx, field_labels = _get_field_labels(
        A_tmp, neighbours=7, **kwargs)
    # a fcn for the labeled_comprehension function that returns
    # linear indices in A where the values in A for each label are
    # greater than half the max in that labeled region

    def fn(val, pos):
        return pos[val > (np.max(val)/2)]
    nLbls = np.max(field_labels)
    indices = ndimage.labeled_comprehension(
        A_tmp, field_labels, np.arange(0, nLbls), fn, np.ndarray, 0, True)
    # turn linear indices into coordinates
    coords = [np.unravel_index(i, np.shape(A)) for i in indices]
    half_peak_labels = np.zeros_like(A)
    for peak_id, coord in enumerate(coords):
        xc, yc = coord
        half_peak_labels[xc, yc] = peak_id

    # Get some statistics about the labeled regions
    # fieldPerim = bwperim(half_peak_labels)
    lbl_range = np.arange(0, nLbls)
    # meanRInLabel = ndimage.mean(A, half_peak_labels, lbl_range)
    # nPixelsInLabel = np.bincount(np.ravel(half_peak_labels.astype(int)))
    # sumRInLabel = ndimage.sum_labels(A, half_peak_labels, lbl_range)
    # maxRInLabel = ndimage.maximum(A, half_peak_labels, lbl_range)
    peak_coords = ndimage.maximum_position(
        A, half_peak_labels, lbl_range)

    # Get some distance and morphology measures
    centre = np.floor(np.array(np.shape(A))/2)
    centred_peak_coords = peak_coords - centre
    peak_dist_to_centre = np.hypot(
        centred_peak_coords.T[0],
        centred_peak_coords.T[1]
        )
    closest_peak_idx = np.argsort(peak_dist_to_centre)
    central_peak_label = closest_peak_idx[0]
    closest_peak_idx = closest_peak_idx[1:np.min((7, len(closest_peak_idx)-1))]
    # closest_peak_idx should now the indices of the labeled 6 peaks
    # surrounding the central peak at the image centre
    scale = np.median(peak_dist_to_centre[closest_peak_idx])
    orientation = np.nan
    orientation = grid_orientation(
        centred_peak_coords, closest_peak_idx)

    central_pt = peak_coords[central_peak_label]
    x = np.linspace(-central_pt[0], central_pt[0], A_sz[0])
    y = np.linspace(-central_pt[1], central_pt[1], A_sz[1])
    xv, yv = np.meshgrid(x, y, indexing='ij')
    dist_to_centre = np.hypot(xv, yv)
    # get the max distance of the half-peak width labeled fields
    # from the centre of the image
    max_dist_from_centre = 0
    for peak_id, _coords in enumerate(coords):
        if peak_id in closest_peak_idx:
            xc, yc = _coords
            if np.any(xc) and np.any(yc):
                xc = xc - np.floor(A_sz[0]/2)
                yc = yc - np.floor(A_sz[1]/2)
                d = np.max(np.hypot(xc, yc))
                if d > max_dist_from_centre:
                    max_dist_from_centre = d
    
    # Set the outer bits and the central region of the SAC to nans
    # getting ready for the correlation procedure
    dist_to_centre[np.abs(dist_to_centre) > max_dist_from_centre] = 0
    dist_to_centre[half_peak_labels == central_peak_label] = 0
    dist_to_centre[dist_to_centre != 0] = 1
    dist_to_centre = dist_to_centre.astype(bool)
    sac_middle = A.copy()
    sac_middle[~dist_to_centre] = np.nan

    if 'step' in kwargs.keys():
        step = kwargs.pop('step')
    else:
        step = 30
    try:
        gridscore, rotationCorrVals, rotationArr = gridness(
            sac_middle, step=step)
    except Exception:
        gridscore, rotationCorrVals, rotationArr = np.nan, np.nan, np.nan

    im_centre = central_pt

    if allProps:
        # attempt to fit an ellipse around the outer edges of the nearest
        # peaks to the centre of the SAC. First find the outer edges for
        # the closest peaks using a ndimages labeled_comprehension
        try:
            def fn2(val, pos):
                xc, yc = np.unravel_index(pos, A_sz)
                xc = xc - np.floor(A_sz[0]/2)
                yc = yc - np.floor(A_sz[1]/2)
                idx = np.argmax(np.hypot(xc, yc))
                return xc[idx], yc[idx]
            ellipse_coords = ndimage.labeled_comprehension(
                A, half_peak_labels, closest_peak_idx, fn2, tuple, 0, True)
        
            ellipse_fit_coords = np.array([(x, y) for x, y in ellipse_coords])
            from skimage.measure import EllipseModel
            E = EllipseModel()
            E.estimate(ellipse_fit_coords)
            im_centre = E.params[0:2]
            ellipse_axes = E.params[2:4]
            ellipse_angle = E.params[-1]
            ellipseXY = E.predict_xy(np.linspace(0, 2*np.pi, 50), E.params)
        
            # get the min containing circle given the eliipse minor axis
            from skimage.measure import CircleModel
            _params = im_centre
            _params.append(np.min(ellipse_axes))
            circleXY = CircleModel().predict_xy(
                np.linspace(0, 2*np.pi, 50), params=_params)
        except (TypeError, ValueError): #  non-iterable x and y i.e. ellipse coords fail
            ellipse_axes = None
            ellipse_angle = (None, None)
            ellipseXY = None
            circleXY = None
        
    # collect all the following keywords into a dict for output
    closest_peak_coords = np.array(peak_coords)[closest_peak_idx]
    dictKeys = (
        'gridscore', 'scale', 'orientation', 'closest_peak_coords',
        'dist_to_centre', 'ellipse_axes',
        'ellipse_angle', 'ellipseXY', 'circleXY', 'im_centre',
        'rotationArr', 'rotationCorrVals')
    outDict = dict.fromkeys(dictKeys, np.nan)
    for thiskey in outDict.keys():
        outDict[thiskey] = locals()[thiskey]
        # neat trick: locals is a dict holding all locally scoped variables
    return outDict
def test_circle_model_invalid_input():
    assert_raises(ValueError, CircleModel().estimate, np.empty((5, 3)))
Beispiel #21
0
    time_idx = np.arange(len(time))
    my_times = split_jobs(comm, time_idx)

    results = []
    fig, ax = plt.subplots(1, 3, figsize=(20, 14))
    for i in tqdm.tqdm(my_times):
        ax[1].set_title('Time {} s'.format(i * 0.33))
        image = red_nseq[i]

        #hist, hist_centers = histogram(image, nbins=10)
        #plt.figure()
        #plt.plot(hist_centers, hist)

        B = image > 0.5 * np.max(image)  #+3*np.std(image)

        ellipse, circle = EllipseModel(), CircleModel()

        hull = array_convex_hull(B)
        x_, y_ = hull.T
        x_ = np.r_[x_, x_[0]]
        y_ = np.r_[y_, y_[0]]
        ellipse.estimate(np.c_[x_, y_])
        circle.estimate(np.c_[x_, y_])

        # Plot original
        ax[0].imshow(red_nseq_bk[i])
        # Auxiliary
        ax[1].imshow(B)

        blue = np.zeros_like(image)
        ax[2].imshow(np.stack([red_nseq_bk[i], green_nseq[i], blue], axis=2))