2015-02-09 130 views
0

我有一個應用程序,我正在使用matplotlib在圖像上顯示橢圓區域。爲此,我使用mpl.patches.Circle和mp.patches.Affine2D將單位圓圈變形爲橢圓形狀。使用matplotlib補丁使用同質變換(非仿射)

import numpy as np 
import matplotlib as mpl 
import pyplot as plt 

invVR_mats = np.array([ 
    [[ 7.80247545, 0.  , 92.9254837 ], 
    [ -3.46026921, 10.85727882, 17.53866959], 
    [ 0.  , 0.  , 1.  ]], 

    [[ 11.42656994, 0.  , 76.86006927], 
    [ -3.26515651, 9.61946297, 24.79440498], 
    [ 0.  , 0.  , 1.  ]], 

    [[ 10.40444851, 0.  , 140.62428284], 
    [ -10.94557095, 10.59212685, 24.91024971], 
    [ 0.  , 0.  , 1.  ]],]) 

invVR_aff2Ds = [mpl.transforms.Affine2D(invVR) 
       for invVR in invVR_mats] 
ell_actors = [mpl.patches.Circle((0, 0), 1, transform=invVR) 
       for invVR in invVR_aff2Ds] 
coll = mpl.collections.PatchCollection(ell_actors) 

plt.figure() 
ax = plt.gca() 
ax.set_ylim(0, 100) 
ax.set_xlim(0, 300) 

ax.add_collection(coll) 

有我的應用程序是,在一個圖像中的省略號使用單應性矩陣被置於對應於橢圓從第二圖像的點。到目前爲止,我一直在使用它來將image1中的點轉換爲image2。

我想了解這些橢圓如何變形成image2。我可以用這個單應性矩陣轉換我的仿射矩陣,但得到的矩陣不再是仿射的。 (我相信這代表了一般的圓錐,無論是圓,橢圓,雙曲線或拋物線)

from numpy.core.umath_tests import matrix_multiply 
H = np.array([[ -0.70098, 0.12273, 5.18734], 
       [ 0.12444, -0.63474, 14.13995], 
       [ 0.00004, 0.00025, -0.64873]]) 

HinvVR_mats = matrix_multiply(H, invVR_mats) 
print(HinvVR_mats) 
#--------- 
np.array([ 
    [[ -5.89405808e+00, 1.33251383e+00, -5.77990446e+01], 
    [ 3.16731132e+00, -6.89154916e+00, 1.45711021e+01], 
    [ -5.52968284e-04, 2.71431970e-03, -6.40628313e-01]], 

    [[ -8.41052966e+00, 1.18059669e+00, -4.56470140e+01], 
    [ 3.49444781e+00, -6.10585793e+00, 7.96641640e+00], 
    [ -3.59226330e-04, 2.40486574e-03, -6.39456996e-01]], 

    [[ -8.63666024e+00, 1.29997173e+00, -9.03302348e+01], 
    [ 8.24232128e+00, -6.72324660e+00, 1.58277039e+01], 
    [ -2.32021480e-03, 2.64803171e-03, -6.36877466e-01]]]) 

如果我去均質只有最後一列,我可以找到在橢圓被射出的中心,但我也希望看到一些形狀信息。

到目前爲止,我所做的只是去均質化的最後一列,並忽略值的最佳[:2,0]和[:,2,1]

HinvVR_mats = np.divide(HinvVR_mats , HinvVR_mats[:, None, None, 2, 2]) 
print(HinvVR_mats) 

array([[[ 9.20043332e+00, -2.08001083e+00, 9.02224323e+01], 
    [ -4.94407015e+00, 1.07574845e+01, -2.27450173e+01], 
    [ 8.63165541e-04, -4.23696494e-03, 1.00000000e+00]], 

    [[ 1.31526118e+01, -1.84624877e+00, 7.13840248e+01], 
    [ -5.46471120e+00, 9.54850438e+00, -1.24580956e+01], 
    [ 5.61767769e-04, -3.76079354e-03, 1.00000000e+00]], 

    [[ 1.35609449e+01, -2.04116458e+00, 1.41832989e+02], 
    [ -1.29417694e+01, 1.05565779e+01, -2.48520394e+01], 
    [ 3.64311021e-03, -4.15783546e-03, 1.00000000e+00]]]) 

是否有我可以使用非仿射矩陣變換mpl.patches.Circle(或其他任何補丁)。文件似乎表明這是可能的,但我沒有看到任何方式去做。

+0

我應該我不明白足夠變換棧,但MPL不支持非仿射變換的http:// matplotlib .org/users/transforms_tutorial.html並不是一個糟糕的地方。 – tacaswell 2015-02-09 13:58:58

回答

0

我能夠通過查看張貼tcaswell教程來解決這個

我要創建我自己的穿越 - 類看起來像這樣

class HomographyTransform(mpl.transforms.Transform): 
    """ 
    References: 
     http://stackoverflow.com/questions/28401788/using-homogeneous-transforms-non-affine-with-matplotlib-patches?noredirect=1#comment45156353_28401788 
     http://matplotlib.org/users/transforms_tutorial.html 
    """ 
    input_dims = 2 
    output_dims = 2 
    is_separable = False 

    def __init__(self, H, axis=None, use_rmin=True): 
     mpl.transforms.Transform.__init__(self) 
     self._axis = axis 
     self._use_rmin = use_rmin 
     self.H = H 

    def transform_non_affine(self, input_xy): 
     """ 
     The input and output are Nx2 numpy arrays. 
     """ 
     import vtool as vt 
     _xys = input_xy.T 
     xyz = vt.add_homogenous_coordinate(_xys) 
     xyz_t = vt.matrix_multiply(self.H, xyz) 
     xy_t = vt.remove_homogenous_coordinate(xyz_t) 
     output_xy = xy_t.T 
     return output_xy 
    #transform_non_affine.__doc__ = mpl.transforms.Transform.transform_non_affine.__doc__ 

    def transform_path_non_affine(self, path): 
     vertices = path.vertices 
     if len(vertices) == 2 and vertices[0, 0] == vertices[1, 0]: 
      return mpl.path.Path(self.transform(vertices), path.codes) 
     ipath = path.interpolated(path._interpolation_steps) 
     return mpl.path.Path(self.transform(ipath.vertices), ipath.codes) 
    #transform_path_non_affine.__doc__ = mpl.transforms.Transform.transform_path_non_affine.__doc__ 

的功能雖然稱爲我自己的圖書館vtool是:

def add_homogenous_coordinate(_xys): 
    assert _xys.shape[0] == 2 
    _zs = np.ones((1, _xys.shape[1]), dtype=_xys.dtype) 
    _xyzs = np.vstack((_xys, _zs)) 
    return _xyzs 


def remove_homogenous_coordinate(_xyzs): 
    assert _xyzs.shape[0] == 3 
    _xys = np.divide(_xyzs[0:2], _xyzs[None, 2]) 
    return _xys 

和matri x_multiply與之前使用的matrix_multiply相同。

和我的函數來創建變換矩陣目前看起來是這樣的:

def get_invVR_aff2Ds(kpts, H=None): 
    """ Returns matplotlib keypoint transformations (circle -> ellipse) """ 
    #invVR_mats = ktool.get_invV_mats(kpts, with_trans=True, with_ori=True) 
    invVR_mats = ktool.get_invVR_mats3x3(kpts) 
    if H is None: 
     invVR_aff2Ds = [mpl.transforms.Affine2D(invVR) 
         for invVR in invVR_mats] 
    else: 
     # not actually affine 
     invVR_aff2Ds = [HomographyTransform(H.dot(invVR)) 
         for invVR in invVR_mats] 
    return invVR_aff2Ds