示例#1
0
    def step_7_ellipse_fit(self):
        """
        Extract the cylinder and ellipse diameter of each stem        

        Args:
            None

        Returns:
            None
        """
        for i in self.finalstems:
            # if the tree points has enough points to fit a ellipse
            if len(i['tree']) > 5:
                # find a matrix that rotates the stem to be colinear to the z axis
                R = utils.rotation_matrix_from_vectors(i['model'][3:6],
                                                       [0, 0, 1])
                # we center the stem to the origen then rotate it
                centeredtree = i['tree'] - i['model'][0:3]
                correctedcyl = (R @ centeredtree.T).T
                # fit an ellipse using only the xy coordinates
                reg = LsqEllipse().fit(correctedcyl[:, 0:2])
                center, a, b, phi = reg.as_parameters()

                ellipse_diameter = (3 * (a + b) - np.sqrt(
                    (3 * a + b) * (a + 3 * b)))
                cylinder_diameter = i['model'][6] * 2
                i['cylinder_diameter'] = cylinder_diameter
                i['ellipse_diameter'] = ellipse_diameter
                i['final_diameter'] = max(ellipse_diameter, cylinder_diameter)
            else:
                i['cylinder_diameter'] = None
                i['ellipse_diameter'] = None
                i['final_diameter'] = None
def test_if_perfect_circle():
    X = make_dataset(center=[0, 0], width=1, height=1, phi=0, n_points=50)

    elp = LsqEllipse().fit(X)
    _center, _width, _height, _phi = elp.as_parameters()

    nptest.assert_array_almost_equal(_center, [0, 0])
    nptest.assert_almost_equal(_width, 1)
    nptest.assert_almost_equal(_height, 1)
def test_minimum_data_points():
    X = make_dataset(center=[0, 0], width=1, height=.5, phi=0, n_points=5)
    elp = LsqEllipse()
    elp.fit(X)
    _center, _width, _height, _phi = elp.as_parameters()

    nptest.assert_array_almost_equal(_center, [0, 0])
    nptest.assert_almost_equal(_width, 1)
    nptest.assert_almost_equal(_height, .5)
    nptest.assert_almost_equal(_phi, 0)
def test_return_fit_returns_correct_ellipse(n_points):
    X = make_dataset(center=[0, 0],
                     width=1,
                     height=.5,
                     phi=0,
                     n_points=n_points)

    elp = LsqEllipse().fit(X)
    x = elp.return_fit(n_points)

    nptest.assert_array_almost_equal(x, X)
def test_if_no_ellipse_found():
    """
    This data causes a divide by zero error
    TODO: add in check of this
    """
    X = make_dataset(center=[0, 0], width=1, height=1, phi=0, n_points=5)

    elp = LsqEllipse().fit(X)
    _center, _width, _height, _phi = elp.as_parameters()

    nptest.assert_array_almost_equal(_center, [0, 0])
    nptest.assert_almost_equal(_width, 1)
    nptest.assert_almost_equal(_height, 1)
def test_ellipse_fit(center, width, height, phi):
    X = make_dataset(center=center,
                     width=width,
                     height=height,
                     phi=phi,
                     n_points=10)
    elp = LsqEllipse()
    elp.fit(X)
    _center, _width, _height, _phi = elp.as_parameters()

    nptest.assert_array_almost_equal(_center, center)
    nptest.assert_almost_equal(_width, width)
    nptest.assert_almost_equal(_height, height)
    nptest.assert_almost_equal(_phi, phi)
def test_return_fit_returns_correct_ellipse(n_points):
    X = make_dataset(center=[0, 0],
                     width=1,
                     height=.5,
                     phi=0,
                     n_points=n_points)

    elp = LsqEllipse().fit(X)
    t = np.linspace(0, 1.8 * np.pi, n_points)
    center, major, minor, phi = elp.as_parameters()
    with mock.patch.object(LsqEllipse, 'as_parameters') as as_parameters:
        as_parameters.return_value = (center,
                                      *_normalize_result(major, minor, phi))
        x = elp.return_fit(n_points, t=t)

    nptest.assert_array_almost_equal(x, X)
def test_minimum_data_points():
    X = make_dataset(center=[0, 0],
                     width=1,
                     height=.5,
                     phi=np.pi / 20,
                     n_points=5)
    elp = LsqEllipse()
    elp.fit(X)
    _center, _major, _minor, _phi = elp.as_parameters()

    _width, _height, _phi = _normalize_result(_major, _minor, _phi)

    nptest.assert_array_almost_equal(_center, [0, 0])
    nptest.assert_almost_equal(_width, 1)
    nptest.assert_almost_equal(_height, .5)
    nptest.assert_almost_equal(_phi, np.pi / 20)
示例#9
0
def ellipse_fit(image):
    '''
	Dada uma imagem binária, extrai os pixels brancos como vértices e busca uma
	elipse que se encaixe neles.

	Parâmetros:
		image (np.array): array contendo os pixels da imagem.

	Retorno:
		ellipse_data (ellipse.LsqEllipse): elipse detectada.
	'''

    white_pixels = np.argwhere(image == 255)
    ellipse_data = LsqEllipse().fit(white_pixels)
    center, width, height, angle = ellipse_data.as_parameters()
    center = (center[1], center[0])
    ellipse_data = (center, (width * 2, height * 2), angle)
    return ellipse_data
示例#10
0
    def get_distance_func(self, phi, index):
        '''
        Compute the ellipse parameters and the distance of each
        pixel position to this ellipse (Shape prior)

        Args:
            phi: Signed distance function at the kth iteration
            index: List of indexes of the points that are close to the level-set zero
                of the phi function. This will provide a set of points from
                which to compute the ellipse

        Returns:
            2D array of the size of the original image, where each pixel value represents
            the distance from that pixel position to the estimated ellipse. This distance
            is normalized so all the distances values are between 0 and 1.
        '''
        # We need at least 6 points to have an unique solution. If we don't, then
        # we skip this distance function
        if (index[0].shape[0]) < 6:
            return np.zeros(phi.shape)
        index = np.array(index, dtype=np.float)

        index = np.swapaxes(index, 0, 1)
        # The Ellipse module requires to have as first index X and the second
        # index Y, which is the inverse of our code
        index[:, [0, 1]] = index[:, [1, 0]]

        reg = LsqEllipse().fit(index)
        a, b, c, d, e, f = reg.coefficients

        xv, yv = np.meshgrid(range(phi.shape[1]), range(phi.shape[0]))
        xv_2 = np.power(xv, 2)
        yv_2 = np.power(yv, 2)
        xv_yv = np.multiply(xv, yv)
        distances = a * xv_2 + b * xv_yv + c * yv_2 + d * xv + e * yv + f

        distances /= (np.max(np.absolute(distances)) + 1)
        return distances
    t = np.linspace(0, 2 * np.pi, 1000)
    x_noise, y_noise = np.random.rand(2, len(t))

    ellipse_x = center[0] + width * np.cos(t) * np.cos(phi) - height * np.sin(
        t) * np.sin(phi) + x_noise / 2.  # noqa: E501
    ellipse_y = center[1] + width * np.cos(t) * np.sin(phi) + height * np.sin(
        t) * np.cos(phi) + y_noise / 2.  # noqa: E501

    return [ellipse_x, ellipse_y]


if __name__ == '__main__':
    X1, X2 = make_test_ellipse()

    X = np.array(list(zip(X1, X2)))
    reg = LsqEllipse().fit(X)
    center, width, height, phi = reg.as_parameters()

    print(f'center: {center[0]:.3f}, {center[1]:.3f}')
    print(f'width: {width:.3f}')
    print(f'height: {height:.3f}')
    print(f'phi: {phi:.3f}')

    fig = plt.figure(figsize=(6, 6))
    ax = plt.subplot()
    ax.axis('equal')
    ax.plot(X1, X2, 'ro', zorder=1)
    ellipse = Ellipse(xy=center,
                      width=2 * width,
                      height=2 * height,
                      angle=np.rad2deg(phi),
def test_cannot_get_coef_without_fitting():
    elp = LsqEllipse()
    with pytest.raises(ValueError):
        elp.coefficients
def test_less_than_minimum_data_points_raises_err():
    X = make_dataset(center=[0, 0], width=1, height=.5, phi=0, n_points=4)
    elp = LsqEllipse()
    with pytest.raises(ValueError):
        elp.fit(X)
示例#14
0
def ellipse_fit(data):
    X = data[:, 0, 0]
    Y = data[:, 0, 1]
    Z = np.array(list(zip(X, Y)))
    reg = LsqEllipse().fit(Z)
    return reg