使用带有matplotlib补丁的齐次变换(非仿射)

2024-05-23 21:53:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个应用程序,我使用matplotlib在图像上显示椭圆区域。我用的是mpl.patches.Circle随着mp.patches.Affine2D将单位圆扭曲成椭圆形。在

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。在

我想知道这些椭圆是如何扭曲成图像2的。我可以用这个单应矩阵变换我的仿射矩阵,但是得到的矩阵不再是仿射的。(我相信它代表一般的二次曲线,可以是圆、椭圆、双曲线或抛物线)

^{pr2}$

如果我只去均匀化最后一列,我可以找到椭圆投影的中心,但我也希望看到一些形状信息。在

到目前为止,我所做的最好的就是对最后一列进行去均匀化处理,忽略[:,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(或任何其他补丁)使用非仿射矩阵。文件似乎表明这是可能的,但我看不出任何办法。在

我有


Tags: 图像import应用程序asnpplt矩阵ax
1条回答
网友
1楼 · 发布于 2024-05-23 21:53:29

我可以通过查看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调用的函数有:

^{pr2}$

乘以u和前面的u矩阵是相同的。在

我创建转换矩阵的功能如下:

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

相关问题 更多 >