Beispiel #1
0
def _annotate_kpts(kpts, sel_fx, draw_ell, draw_pts, color=None, nRandKpts=None, rect=False):
    #print('[viz] _annotate_kpts()')
    if color is None:
        color = 'distinct' if sel_fx is None else df2.ORANGE
    ell_args = {
        'ell': draw_ell,
        'pts': draw_pts,
        'rect': rect,
        'ell_alpha': .4,
        'ell_linewidth': 2,
        'ell_color': color,
    }
    if draw_ell and nRandKpts is not None:
        # show a random sample of kpts
        nkpts1 = len(kpts)
        fxs1 = np.arange(nkpts1)
        size = nRandKpts
        replace = False
        p = np.ones(nkpts1)
        p = p / p.sum()
        fxs_randsamp = np.random.choice(fxs1, size, replace, p)
        kpts = kpts[fxs_randsamp]
        # TODO Fix this. This should not set the xlabel
        df2.set_xlabel('displaying %r/%r keypoints' % (nRandKpts, nkpts1))
    elif draw_ell or draw_pts:
        # draw all keypoints
        df2.draw_kpts2(kpts, **ell_args)
    if sel_fx is not None:
        # Draw selected keypoint
        sel_kpts = kpts[sel_fx:sel_fx + 1]
        df2.draw_kpts2(sel_kpts, ell_color=df2.BLUE, arrow=True, rect=True)
Beispiel #2
0
def draw_keypoint_patch(rchip, kp, sift=None, warped=False, **kwargs):
    #print('--------------------')
    #print('[extract] Draw Patch')
    if warped:
        wpatch, wkp = get_warped_patch(rchip, kp)
        patch = wpatch
        subkp = wkp
    else:
        patch, subkp = get_patch(rchip, kp)
    #print('[extract] kp    = '+str(kp))
    #print('[extract] subkp = '+str(subkp))
    #print('[extract] patch.shape = %r' % (patch.shape,))
    color = (0, 0, 1)
    fig, ax = df2.imshow(patch, **kwargs)
    df2.draw_kpts2([subkp], ell_color=color, pts=True)
    if not sift is None:
        df2.draw_sift(sift, [subkp])
    return ax
Beispiel #3
0
def draw_keypoint_patch(rchip, kp, sift=None, warped=False, **kwargs):
    #print('--------------------')
    #print('[extract] Draw Patch')
    if warped:
        wpatch, wkp = get_warped_patch(rchip, kp)
        patch = wpatch
        subkp = wkp
    else:
        patch, subkp = get_patch(rchip, kp)
    #print('[extract] kp    = '+str(kp))
    #print('[extract] subkp = '+str(subkp))
    #print('[extract] patch.shape = %r' % (patch.shape,))
    color = (0, 0, 1)
    fig, ax = df2.imshow(patch, **kwargs)
    df2.draw_kpts2([subkp], ell_color=color, pts=True)
    if not sift is None:
        df2.draw_sift(sift, [subkp])
    return ax
Beispiel #4
0
def _annotate_kpts(kpts,
                   sel_fx,
                   draw_ell,
                   draw_pts,
                   color=None,
                   nRandKpts=None,
                   rect=False):
    #print('[viz] _annotate_kpts()')
    if color is None:
        color = 'distinct' if sel_fx is None else df2.ORANGE
    ell_args = {
        'ell': draw_ell,
        'pts': draw_pts,
        'rect': rect,
        'ell_alpha': .4,
        'ell_linewidth': 2,
        'ell_color': color,
    }
    if draw_ell and nRandKpts is not None:
        # show a random sample of kpts
        nkpts1 = len(kpts)
        fxs1 = np.arange(nkpts1)
        size = nRandKpts
        replace = False
        p = np.ones(nkpts1)
        p = p / p.sum()
        fxs_randsamp = np.random.choice(fxs1, size, replace, p)
        kpts = kpts[fxs_randsamp]
        # TODO Fix this. This should not set the xlabel
        df2.set_xlabel('displaying %r/%r keypoints' % (nRandKpts, nkpts1))
    elif draw_ell or draw_pts:
        # draw all keypoints
        df2.draw_kpts2(kpts, **ell_args)
    if sel_fx is not None:
        # Draw selected keypoint
        sel_kpts = kpts[sel_fx:sel_fx + 1]
        df2.draw_kpts2(sel_kpts, ell_color=df2.BLUE, arrow=True, rect=True)
def test(hs, qcx):
    fx2_scale = sv2.keypoint_scale(hs.feats.cx2_kpts[qcx])
    fx = fx2_scale.argsort()[::-1][40]
    rchip = hs.get_chip(qcx)
    kp = hs.feats.cx2_kpts[qcx][fx]
    # Show full image and keypoint
    df2.figure(fignum=9000, doclf=True)
    df2.imshow(rchip, plotnum=(1,3,1))
    df2.draw_kpts2([kp], ell_color=(1,0,0), pts=True)
    # Show cropped image and keypoint
    patch, subkp = get_patch(rchip, kp)
    df2.imshow(patch, plotnum=(1,3,2))
    df2.draw_kpts2([subkp], ell_color=(1,0,0), pts=True)
    # Show warped image and keypoint
    wpatch, wkp = get_warped_patch(rchip, kp)
    df2.imshow(wpatch, plotnum=(1,3,3))
    df2.draw_kpts2([wkp], ell_color=(1,0,0), pts=True)
    #
    df2.set_figtitle('warp test')
Beispiel #6
0
 def _kpts_helper(kpts_, color, alpha, label):
     # helper function taking into acount phantom labels
     df2.draw_kpts2(kpts_, ell_color=color, ell_alpha=alpha)
     df2.phantom_legend_label(label, color)
Beispiel #7
0
 def _kpts_helper(kpts_, color, alpha, label):
     # helper function taking into acount phantom labels
     df2.draw_kpts2(kpts_, ell_color=color, ell_alpha=alpha)
     df2.phantom_legend_label(label, color)
Beispiel #8
0
def in_depth_ellipse2x2(rchip, kp):
    #-----------------------
    # SETUP
    #-----------------------
    from hotspotter import draw_func2 as df2
    np.set_printoptions(precision=8)
    tau = 2 * np.pi
    df2.reset()
    df2.figure(9003, docla=True, doclf=True)
    ax = df2.gca()
    ax.invert_yaxis()

    def _plotpts(data, px, color=df2.BLUE, label=''):
        #df2.figure(9003, docla=True, pnum=(1, 1, px))
        df2.plot2(data.T[0], data.T[1], '.', '', color=color, label=label)
        df2.update()

    def _plotarrow(x, y, dx, dy, color=df2.BLUE, label=''):
        ax = df2.gca()
        arrowargs = dict(head_width=.5, length_includes_head=True, label=label)
        arrow = df2.FancyArrow(x, y, dx, dy, **arrowargs)
        arrow.set_edgecolor(color)
        arrow.set_facecolor(color)
        ax.add_patch(arrow)
        df2.update()

    def _2x2_eig(M2x2):
        (evals, evecs) = np.linalg.eig(M2x2)
        l1, l2 = evals
        v1, v2 = evecs
        return l1, l2, v1, v2

    #-----------------------
    # INPUT
    #-----------------------
    # We will call perdoch's invA = invV
    print('--------------------------------')
    print('Let V = Perdoch.A')
    print('Let Z = Perdoch.E')
    print('--------------------------------')
    print('Input from Perdoch\'s detector: ')

    # We are given the keypoint in invA format
    (x, y, ia11, ia21, ia22), ia12 = kp, 0
    invV = np.array([[ia11, ia12], [ia21, ia22]])
    V = np.linalg.inv(invV)
    # <HACK>
    #invV = V / np.linalg.det(V)
    #V = np.linalg.inv(V)
    # </HACK>
    Z = (V.T).dot(V)

    print('invV is a transform from points on a unit-circle to the ellipse')
    helpers.horiz_print('invV = ', invV)
    print('--------------------------------')
    print('V is a transformation from points on the ellipse to a unit circle')
    helpers.horiz_print('V = ', V)
    print('--------------------------------')
    print('Points on a matrix satisfy (x).T.dot(Z).dot(x) = 1')
    print('where Z = (V.T).dot(V)')
    helpers.horiz_print('Z = ', Z)

    # Define points on a unit circle
    theta_list = np.linspace(0, tau, 50)
    cicrle_pts = np.array([(np.cos(t), np.sin(t)) for t in theta_list])

    # Transform those points to the ellipse using invV
    ellipse_pts1 = invV.dot(cicrle_pts.T).T

    # Transform those points to the ellipse using V
    ellipse_pts2 = V.dot(cicrle_pts.T).T

    #Lets check our assertion: (x_).T.dot(Z).dot(x_) = 1
    checks1 = [x_.T.dot(Z).dot(x_) for x_ in ellipse_pts1]
    checks2 = [x_.T.dot(Z).dot(x_) for x_ in ellipse_pts2]
    assert all([abs(1 - check) < 1E-11 for check in checks1])
    #assert all([abs(1 - check) < 1E-11 for check in checks2])
    print('... all of our plotted points satisfy this')

    #=======================
    # THE CONIC SECTION
    #=======================
    # All of this was from the Perdoch paper, now lets move into conic sections
    # We will use the notation from wikipedia
    # http://en.wikipedia.org/wiki/Conic_section
    # http://en.wikipedia.org/wiki/Matrix_representation_of_conic_sections

    #-----------------------
    # MATRIX REPRESENTATION
    #-----------------------
    # The matrix representation of a conic is:
    (A, B2, B2_, C) = Z.flatten()
    (D, E, F) = (0, 0, 1)
    B = B2 * 2
    assert B2 == B2_, 'matrix should by symmetric'
    print('--------------------------------')
    print('Now, using wikipedia\' matrix representation of a conic.')
    con = np.array((('    A', 'B / 2', 'D / 2'), ('B / 2', '    C', 'E / 2'),
                    ('D / 2', 'E / 2', '    F')))
    helpers.horiz_print('A matrix A_Q = ', con)

    # A_Q is our conic section (aka ellipse matrix)
    A_Q = np.array(((A, B / 2, D / 2), (B / 2, C, E / 2), (D / 2, E / 2, F)))

    helpers.horiz_print('A_Q = ', A_Q)

    #-----------------------
    # DEGENERATE CONICS
    #-----------------------
    print('----------------------------------')
    print('As long as det(A_Q) != it is not degenerate.')
    print('If the conic is not degenerate, we can use the 2x2 minor: A_33')
    print('det(A_Q) = %s' % str(np.linalg.det(A_Q)))
    assert np.linalg.det(A_Q) != 0, 'degenerate conic'
    A_33 = np.array(((A, B / 2), (B / 2, C)))
    helpers.horiz_print('A_33 = ', A_33)

    #-----------------------
    # CONIC CLASSIFICATION
    #-----------------------
    print('----------------------------------')
    print('The determinant of the minor classifies the type of conic it is')
    print('(det == 0): parabola, (det < 0): hyperbola, (det > 0): ellipse')
    print('det(A_33) = %s' % str(np.linalg.det(A_33)))
    assert np.linalg.det(A_33) > 0, 'conic is not an ellipse'
    print('... this is indeed an ellipse')

    #-----------------------
    # CONIC CENTER
    #-----------------------
    print('----------------------------------')
    print('the centers of the ellipse are obtained by: ')
    print('x_center = (B * E - (2 * C * D)) / (4 * A * C - B ** 2)')
    print('y_center = (D * B - (2 * A * E)) / (4 * A * C - B ** 2)')
    # Centers are obtained by solving for where the gradient of the quadratic
    # becomes 0. Without going through the derivation the calculation is...
    # These should be 0, 0 if we are at the origin, or our original x, y
    # coordinate specified by the keypoints. I'm doing the calculation just for
    # shits and giggles
    x_center = (B * E - (2 * C * D)) / (4 * A * C - B**2)
    y_center = (D * B - (2 * A * E)) / (4 * A * C - B**2)
    helpers.horiz_print('x_center = ', x_center)
    helpers.horiz_print('y_center = ', y_center)

    #-----------------------
    # MAJOR AND MINOR AXES
    #-----------------------
    # Now we are going to determine the major and minor axis
    # of this beast. It just the center augmented by the eigenvecs
    print('----------------------------------')

    # The angle between the major axis and our x axis is:
    l1, l2, v1, v2 = _2x2_eig(A_33)
    x_axis = np.array([1, 0])
    theta = np.arccos(x_axis.dot(v1))

    # The eccentricity is determined by:
    nu = 1
    numer = 2 * np.sqrt((A - C)**2 + B**2)
    denom = nu * (A + C) + np.sqrt((A - C)**2 + B**2)
    eccentricity = np.sqrt(numer / denom)

    from scipy.special import ellipeinc
    #-----------------------
    # DRAWING
    #-----------------------
    # Lets start off by drawing the ellipse that we are goign to work with
    # Create unit circle sample

    # Draw the keypoint using the tried and true df2
    # Other things should subsiquently align
    df2.draw_kpts2(np.array([(0, 0, ia11, ia21, ia22)]),
                   ell_linewidth=4,
                   ell_color=df2.DEEP_PINK,
                   ell_alpha=1,
                   arrow=True,
                   rect=True)

    # Plot ellipse points
    _plotpts(ellipse_pts1, 0, df2.YELLOW, label='invV.dot(cicrle_pts.T).T')

    # Plot ellipse axis
    # !HELP! I DO NOT KNOW WHY I HAVE TO DIVIDE, SQUARE ROOT, AND NEGATE!!!
    l1, l2, v1, v2 = _2x2_eig(A_33)
    dx1, dy1 = (v1 / np.sqrt(l1))
    dx2, dy2 = (v2 / np.sqrt(l2))
    _plotarrow(0, 0, dx1, -dy1, color=df2.ORANGE, label='ellipse axis')
    _plotarrow(0, 0, dx2, -dy2, color=df2.ORANGE)

    # Plot ellipse orientation
    orient_axis = invV.dot(np.eye(2))
    dx1, dx2, dy1, dy2 = orient_axis.flatten()
    _plotarrow(0, 0, dx1, dy1, color=df2.BLUE, label='ellipse rotation')
    _plotarrow(0, 0, dx2, dy2, color=df2.BLUE)

    df2.legend()
    df2.dark_background()
    df2.gca().invert_yaxis()
    return locals()
 def draw_one_kp(patch, kp, plotx, color, desc=None):
     fig, ax = df2.imshow(patch, plotnum=(num_rows, num_cols, plotx))
     df2.draw_kpts2([kp], ell_color=color, pts=True)
     if not desc is None and not '--nodesc' in sys.argv:
         df2.draw_sift(desc, [kp])
     df2.draw_border(ax, color, 1)
def viz_top_features(hs, res, low, high, fignum=0, draw_chips=True):
    from collections import defaultdict
    qcx = res.qcx
    cx2_nx = hs.tables.cx2_nx
    top_patches_list = get_top_scoring_patches(hs, res, low, high)
    num_rows = high-low
    num_cols = 4
    if params.__MATCH_TYPE__ == 'vsmany':
        num_cols = 6
    # Initialize Figure
    fig = df2.figure(fignum+1, plotnum=(num_rows, num_cols,1))
    cx2_rchip = defaultdict(int)
    cx2_kplist = defaultdict(list)
    def draw_one_kp(patch, kp, plotx, color, desc=None):
        fig, ax = df2.imshow(patch, plotnum=(num_rows, num_cols, plotx))
        df2.draw_kpts2([kp], ell_color=color, pts=True)
        if not desc is None and not '--nodesc' in sys.argv:
            df2.draw_sift(desc, [kp])
        df2.draw_border(ax, color, 1)

    for tx, (patches1, patches2, patchesN, cx, feat_score) in enumerate(top_patches_list):
        (kp1, subkp1, wkp1, patch1, wpatch1, cx1, desc1) = patches1
        (kp2, subkp2, wkp2, patch2, wpatch2, cx2, desc2) = patches2
        # draw on table
        # Draw Query Keypoint
        plotx = (tx*num_cols)
        draw_one_kp(patch1,  subkp1, plotx+1, df2.GREEN, desc1)
        qnx = cx2_nx[qcx]
        df2.plt.gca().set_xlabel('qcx=%r; qnx=%r' % (qcx, qnx))
        draw_one_kp(wpatch1, wkp1,   plotx+2, df2.GREEN, desc1)

        # Draw ith < k match
        draw_one_kp(patch2,  subkp2, plotx+3, df2.BLUE, desc2)
        nx = cx2_nx[cx]
        df2.plt.gca().set_xlabel('cx=%r; nx=%r' % (cx, nx))
        draw_one_kp(wpatch2, wkp2,   plotx+4, df2.BLUE, desc2)
        df2.plt.gca().set_xlabel('score=%r' % (feat_score))

        # Draw k+1th match
        if params.__MATCH_TYPE__ == 'vsmany':
            (kpN, subkpN, wkpN, patchN, wpatchN, cxN, descN) = patchesN
            draw_one_kp(patchN,  subkpN, plotx+5, df2.ORANGE, descN)
            nxN = cx2_nx[qcx]
            df2.plt.gca().set_xlabel('cxN=%r; nxN=%r' % (cxN, nxN))
            draw_one_kp(wpatchN, wkpN,   plotx+6, df2.ORANGE, descN)
        # Get other info
        cx2_rchip[cx] = hs.get_chip(cx)
        cx2_kplist[qcx].append(kp1)
        cx2_kplist[cx].append(kp2)
    # Draw annotations on
    df2.figure(plotnum=(num_rows, num_cols,1), title='Query Patch')
    df2.figure(plotnum=(num_rows, num_cols,2), title='Query Patch')
    df2.figure(plotnum=(num_rows, num_cols,3), title='Result Patch')
    df2.figure(plotnum=(num_rows, num_cols,4), title='Result Warped')

    if params.__MATCH_TYPE__ == 'vsmany':
        df2.figure(plotnum=(num_rows, num_cols,5), title='Normalizer Patch')
        df2.figure(plotnum=(num_rows, num_cols,6), title='Normalizer Warped')

    df2.set_figtitle('Top '+str(low)+' to '+str(high)+' scoring matches')
    if not draw_chips:
        return
    #
    # Draw on full images
    cx2_rchip[qcx] = hs.get_chip(qcx)
    cx_keys  = cx2_kplist.keys()
    cx_vals = map(len, cx2_kplist.values())
    cx_list = [x for (y,x) in sorted(zip(cx_vals, cx_keys))][::-1]
    num_chips = len(cx_list)
    pltnum_fn = lambda ix: (int(np.ceil(num_chips/2)), 2, ix)
    plotnum = pltnum_fn(1)
    fig2 = df2.figure(fignum-1, plotnum=plotnum)
    for ix, cx in enumerate(cx_list):
        plotnum = pltnum_fn(ix+1)
        fig2 = df2.figure(fignum-1, plotnum=plotnum)
        rchip = cx2_rchip[cx]
        fig, ax = df2.imshow(rchip)
        title_pref = ''
        color = df2.BLUE
        if res.qcx == cx:
            title_pref = 'q'
            color = df2.GREEN
        df2.draw_kpts2(cx2_kplist[cx], ell_color=color, ell_alpha=1)
        df2.draw_border(ax, color, 2)
        nx = cx2_nx[cx]
        ax.set_title(title_pref+'cx = %r; nx=%r' % (cx, nx))
        gname = hs.get_gname(cx)
        ax.set_xlabel(gname)
Beispiel #11
0
def in_depth_ellipse2x2(rchip, kp):
    #-----------------------
    # SETUP
    #-----------------------
    from hotspotter import draw_func2 as df2
    np.set_printoptions(precision=8)
    tau = 2 * np.pi
    df2.reset()
    df2.figure(9003, docla=True, doclf=True)
    ax = df2.gca()
    ax.invert_yaxis()

    def _plotpts(data, px, color=df2.BLUE, label=''):
        #df2.figure(9003, docla=True, pnum=(1, 1, px))
        df2.plot2(data.T[0], data.T[1], '.', '', color=color, label=label)
        df2.update()

    def _plotarrow(x, y, dx, dy, color=df2.BLUE, label=''):
        ax = df2.gca()
        arrowargs = dict(head_width=.5, length_includes_head=True, label=label)
        arrow = df2.FancyArrow(x, y, dx, dy, **arrowargs)
        arrow.set_edgecolor(color)
        arrow.set_facecolor(color)
        ax.add_patch(arrow)
        df2.update()

    def _2x2_eig(M2x2):
        (evals, evecs) = np.linalg.eig(M2x2)
        l1, l2 = evals
        v1, v2 = evecs
        return l1, l2, v1, v2

    #-----------------------
    # INPUT
    #-----------------------
    # We will call perdoch's invA = invV
    print('--------------------------------')
    print('Let V = Perdoch.A')
    print('Let Z = Perdoch.E')
    print('--------------------------------')
    print('Input from Perdoch\'s detector: ')

    # We are given the keypoint in invA format
    (x, y, ia11, ia21, ia22), ia12 = kp, 0
    invV = np.array([[ia11, ia12],
                     [ia21, ia22]])
    V = np.linalg.inv(invV)
    # <HACK>
    #invV = V / np.linalg.det(V)
    #V = np.linalg.inv(V)
    # </HACK>
    Z = (V.T).dot(V)

    print('invV is a transform from points on a unit-circle to the ellipse')
    helpers.horiz_print('invV = ', invV)
    print('--------------------------------')
    print('V is a transformation from points on the ellipse to a unit circle')
    helpers.horiz_print('V = ', V)
    print('--------------------------------')
    print('Points on a matrix satisfy (x).T.dot(Z).dot(x) = 1')
    print('where Z = (V.T).dot(V)')
    helpers.horiz_print('Z = ', Z)

    # Define points on a unit circle
    theta_list = np.linspace(0, tau, 50)
    cicrle_pts = np.array([(np.cos(t), np.sin(t)) for t in theta_list])

    # Transform those points to the ellipse using invV
    ellipse_pts1 = invV.dot(cicrle_pts.T).T

    # Transform those points to the ellipse using V
    ellipse_pts2 = V.dot(cicrle_pts.T).T

    #Lets check our assertion: (x_).T.dot(Z).dot(x_) = 1
    checks1 = [x_.T.dot(Z).dot(x_) for x_ in ellipse_pts1]
    checks2 = [x_.T.dot(Z).dot(x_) for x_ in ellipse_pts2]
    assert all([abs(1 - check) < 1E-11 for check in checks1])
    #assert all([abs(1 - check) < 1E-11 for check in checks2])
    print('... all of our plotted points satisfy this')

    #=======================
    # THE CONIC SECTION
    #=======================
    # All of this was from the Perdoch paper, now lets move into conic sections
    # We will use the notation from wikipedia
    # http://en.wikipedia.org/wiki/Conic_section
    # http://en.wikipedia.org/wiki/Matrix_representation_of_conic_sections

    #-----------------------
    # MATRIX REPRESENTATION
    #-----------------------
    # The matrix representation of a conic is:
    (A,  B2, B2_, C) = Z.flatten()
    (D, E, F) = (0, 0, 1)
    B = B2 * 2
    assert B2 == B2_, 'matrix should by symmetric'
    print('--------------------------------')
    print('Now, using wikipedia\' matrix representation of a conic.')
    con = np.array((('    A', 'B / 2', 'D / 2'),
                    ('B / 2', '    C', 'E / 2'),
                    ('D / 2', 'E / 2', '    F')))
    helpers.horiz_print('A matrix A_Q = ', con)

    # A_Q is our conic section (aka ellipse matrix)
    A_Q = np.array(((    A, B / 2, D / 2),
                    (B / 2,     C, E / 2),
                    (D / 2, E / 2,     F)))

    helpers.horiz_print('A_Q = ', A_Q)

    #-----------------------
    # DEGENERATE CONICS
    #-----------------------
    print('----------------------------------')
    print('As long as det(A_Q) != it is not degenerate.')
    print('If the conic is not degenerate, we can use the 2x2 minor: A_33')
    print('det(A_Q) = %s' % str(np.linalg.det(A_Q)))
    assert np.linalg.det(A_Q) != 0, 'degenerate conic'
    A_33 = np.array(((    A, B / 2),
                     (B / 2,     C)))
    helpers.horiz_print('A_33 = ', A_33)

    #-----------------------
    # CONIC CLASSIFICATION
    #-----------------------
    print('----------------------------------')
    print('The determinant of the minor classifies the type of conic it is')
    print('(det == 0): parabola, (det < 0): hyperbola, (det > 0): ellipse')
    print('det(A_33) = %s' % str(np.linalg.det(A_33)))
    assert np.linalg.det(A_33) > 0, 'conic is not an ellipse'
    print('... this is indeed an ellipse')

    #-----------------------
    # CONIC CENTER
    #-----------------------
    print('----------------------------------')
    print('the centers of the ellipse are obtained by: ')
    print('x_center = (B * E - (2 * C * D)) / (4 * A * C - B ** 2)')
    print('y_center = (D * B - (2 * A * E)) / (4 * A * C - B ** 2)')
    # Centers are obtained by solving for where the gradient of the quadratic
    # becomes 0. Without going through the derivation the calculation is...
    # These should be 0, 0 if we are at the origin, or our original x, y
    # coordinate specified by the keypoints. I'm doing the calculation just for
    # shits and giggles
    x_center = (B * E - (2 * C * D)) / (4 * A * C - B ** 2)
    y_center = (D * B - (2 * A * E)) / (4 * A * C - B ** 2)
    helpers.horiz_print('x_center = ', x_center)
    helpers.horiz_print('y_center = ', y_center)

    #-----------------------
    # MAJOR AND MINOR AXES
    #-----------------------
    # Now we are going to determine the major and minor axis
    # of this beast. It just the center augmented by the eigenvecs
    print('----------------------------------')

    # The angle between the major axis and our x axis is:
    l1, l2, v1, v2 = _2x2_eig(A_33)
    x_axis = np.array([1, 0])
    theta = np.arccos(x_axis.dot(v1))

    # The eccentricity is determined by:
    nu = 1
    numer  = 2 * np.sqrt((A - C) ** 2 + B ** 2)
    denom  = nu * (A + C) + np.sqrt((A - C) ** 2 + B ** 2)
    eccentricity = np.sqrt(numer / denom)

    from scipy.special import ellipeinc
    #-----------------------
    # DRAWING
    #-----------------------
    # Lets start off by drawing the ellipse that we are goign to work with
    # Create unit circle sample

    # Draw the keypoint using the tried and true df2
    # Other things should subsiquently align
    df2.draw_kpts2(np.array([(0, 0, ia11, ia21, ia22)]), ell_linewidth=4,
                   ell_color=df2.DEEP_PINK, ell_alpha=1, arrow=True, rect=True)

    # Plot ellipse points
    _plotpts(ellipse_pts1, 0, df2.YELLOW, label='invV.dot(cicrle_pts.T).T')

    # Plot ellipse axis
    # !HELP! I DO NOT KNOW WHY I HAVE TO DIVIDE, SQUARE ROOT, AND NEGATE!!!
    l1, l2, v1, v2 = _2x2_eig(A_33)
    dx1, dy1 = (v1 / np.sqrt(l1))
    dx2, dy2 = (v2 / np.sqrt(l2))
    _plotarrow(0, 0, dx1, -dy1, color=df2.ORANGE, label='ellipse axis')
    _plotarrow(0, 0, dx2, -dy2, color=df2.ORANGE)

    # Plot ellipse orientation
    orient_axis = invV.dot(np.eye(2))
    dx1, dx2, dy1, dy2 = orient_axis.flatten()
    _plotarrow(0, 0, dx1, dy1, color=df2.BLUE, label='ellipse rotation')
    _plotarrow(0, 0, dx2, dy2, color=df2.BLUE)

    df2.legend()
    df2.dark_background()
    df2.gca().invert_yaxis()
    return locals()