在python中计算图像的特征向量

时间:2012-01-25 15:51:40

标签: python image-processing numpy eigenvector

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

2d more-or-less gaussian distribution

然而,我一直在寻找图像的特征向量 - numpy.linalg.py假设离散数据点。我想过将这个图像作为一个概率分布,对几千个点进行采样,然后根据该分布计算特征向量,但我确信必须有一种找到特征向量的方法(即,半主和半 - 直接来自该图像的高斯椭圆的短轴。有什么想法吗?

非常感谢:)

3 个答案:

答案 0 :(得分:17)

只需快速说明,有几种工具可以将高斯拟合到图像中。我唯一能想到的就是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()

enter image description here

答案 1 :(得分:3)

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

  郭宏伟,“拟合高斯函数的简单算法”IEEE   Signal Processing Magazine,2011年9月,第134--137页

我在这里给出了1D案例的实现:

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

(向下滚动以查看最终的拟合)

答案 2 :(得分:1)

您是否尝试过主成分分析(PCA)?也许MDP package可以用最少的努力完成工作。