【问题标题】:Compute eigenvectors of image in python在python中计算图像的特征向量
【发布时间】:2012-02-18 19:27:49
【问题描述】:

我正在尝试将 2D 高斯拟合到图像中。噪声非常低,所以我尝试旋转图像,使两个主轴不共同变化,找出最大值并计算两个维度的标准偏差。选择的武器是蟒蛇。

但是,我一直在寻找图像的特征向量 - numpy.linalg.py 假设离散数据点。我想把这张图片当作一个概率分布,采样几千个点,然后从那个分布中计算特征向量,但我确信一定有一种方法可以找到特征向量(即,半主要和半高斯椭圆的短轴)直接来自该图像。有什么想法吗?

非常感谢:)

【问题讨论】:

    标签: python image-processing numpy eigenvector


    【解决方案1】:

    请注意,有几种工具可以将高斯拟合到图像中。我唯一能想到的就是scikits.learn,它不是完全面向图像的,但我知道还有其他的。

    完全按照您的想法计算协方差矩阵的特征向量在计算上是非常昂贵的。您必须将图像的每个像素(或较大的随机样本)与 x,y 点相关联。

    基本上,您可以执行以下操作:

        import numpy as np
        # grid is your image data, here...
        grid = np.random.random((10,10))
    
        nrows, ncols = grid.shape
        i,j = np.mgrid[:nrows, :ncols]
        coords = np.vstack((i.reshape(-1), j.reshape(-1), grid.reshape(-1))).T
        cov = np.cov(coords)
        eigvals, eigvecs = np.linalg.eigh(cov)
    

    您可以改为利用它是定期采样的图像这一事实来计算它的矩(或“惯性轴”)。这对于大图像会快得多。

    举个简单的例子,(我正在使用我的previous answers 的一部分,以防你觉得它有用...)

    import numpy as np
    import matplotlib.pyplot as plt
    
    def main():
        data = generate_data()
        xbar, ybar, cov = intertial_axis(data)
    
        fig, ax = plt.subplots()
        ax.imshow(data)
        plot_bars(xbar, ybar, cov, ax)
        plt.show()
    
    def generate_data():
        data = np.zeros((200, 200), dtype=np.float)
        cov = np.array([[200, 100], [100, 200]])
        ij = np.random.multivariate_normal((100,100), cov, int(1e5))
        for i,j in ij:
            data[int(i), int(j)] += 1
        return data 
    
    def raw_moment(data, iord, jord):
        nrows, ncols = data.shape
        y, x = np.mgrid[:nrows, :ncols]
        data = data * x**iord * y**jord
        return data.sum()
    
    def intertial_axis(data):
        """Calculate the x-mean, y-mean, and cov matrix of an image."""
        data_sum = data.sum()
        m10 = raw_moment(data, 1, 0)
        m01 = raw_moment(data, 0, 1)
        x_bar = m10 / data_sum
        y_bar = m01 / data_sum
        u11 = (raw_moment(data, 1, 1) - x_bar * m01) / data_sum
        u20 = (raw_moment(data, 2, 0) - x_bar * m10) / data_sum
        u02 = (raw_moment(data, 0, 2) - y_bar * m01) / data_sum
        cov = np.array([[u20, u11], [u11, u02]])
        return x_bar, y_bar, cov
    
    def plot_bars(x_bar, y_bar, cov, ax):
        """Plot bars with a length of 2 stddev along the principal axes."""
        def make_lines(eigvals, eigvecs, mean, i):
            """Make lines a length of 2 stddev."""
            std = np.sqrt(eigvals[i])
            vec = 2 * std * eigvecs[:,i] / np.hypot(*eigvecs[:,i])
            x, y = np.vstack((mean-vec, mean, mean+vec)).T
            return x, y
        mean = np.array([x_bar, y_bar])
        eigvals, eigvecs = np.linalg.eigh(cov)
        ax.plot(*make_lines(eigvals, eigvecs, mean, 0), marker='o', color='white')
        ax.plot(*make_lines(eigvals, eigvecs, mean, -1), marker='o', color='red')
        ax.axis('image')
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

      【解决方案2】:

      稳健地拟合高斯可能很棘手。 IEEE 信号处理杂志上有一篇关于这个主题的有趣文章:

      郭宏伟,“拟合高斯函数的简单算法”IEEE 信号处理杂志,2011 年 9 月,第 134--137 页

      我在这里给出一维案例的实现:

      http://scipy-central.org/item/28/2/fitting-a-gaussian-to-noisy-data-points

      (向下滚动查看拟合结果)

      【讨论】:

        【解决方案3】:

        您是否尝试过主成分分析 (PCA)?也许MDP package 可以轻松完成这项工作。

        【讨论】:

          猜你喜欢
          • 2016-09-01
          • 2021-09-20
          • 1970-01-01
          • 1970-01-01
          • 2011-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多