同时线性拟合2d numpy数组

时间:2015-08-13 14:17:30

标签: python optimization scipy

我正在使用Python进行图像分析。我有一个图像(2d numpy数组),其中有一些强度漂移。我想要平衡它。

为了消除图像宽度上的增加/减少强度,我想用2行numpy数组的每一行。但是我不想遍历每一行索引。

MWE:

import numpy as np
import matplotlib.pyplot as plt


width=1500
height=2500
np.random.random((width,height))
fill_fun = lambda x,a,b : a*x+b
play_image = fill_fun(np.tile(np.arange(width),(height,1)),0.15,2)+np.random.random( (height,width) )

#For representation purposes:

#plt.imshow(play_image,cmap='Greys_r')
#plt.show()


#1) Fit every row and kill the intensity decrease/increase tendency
fit_func = lambda p,x: p[0]*x+b  
errfunc = lambda p, x, y: abs(fitfunc(p, x) - y) # Distance to the target function
x_axis=np.linspace(0,width,width)

for i in range(height):
    row_val=play_image[i,:]
    p0=[(row_val[-1]-row_val[0])/float(width),row_val[0]] #guess
    p1, success = optimize.leastsq(errfunc, p0[:], args=(x_axis,row_val))
    play_image[i,:]-= fit_func(p1,x_axis)-p1[1]

通过这样做,我有效地水平调整我的图像强度。无论如何我可以通过矩阵运算替换循环吗?以某种方式使用(高度,2)参数向量同时适合所有线?

感谢您的帮助

2 个答案:

答案 0 :(得分:2)

您可以非常轻松地实施normal equations及其解决方案。主要挑战是跟踪适当的尺寸,以便所有矢量化操作都能正常工作。这是一种方法:

import numpy as np


# image size
m = 100
n = 125

# A random image to work with.
np.random.seed(123)
img = np.random.randint(0, 100, size=(m, n))

# X is the design matrix.  It is the same for each row.  It has shape (n, 2).
X = np.column_stack((np.ones(n), np.arange(n)))

# A is X.T.dot(X), but in this case we can use an explicit formula for each term.
s1 = 0.5*n*(n - 1)            # Sum of integers
s2 = n*(n - 0.5)*(n - 1)/3.0  # Sum of squared integers
A = np.array([[n, s1], [s1, s2]])

# Y has shape (2, m).  Each column is a vector on the right-hand-side of the
# normal equations.
Y = X.T.dot(img.T)

# Solve the normal equations.  beta has shape (2, m).  Each column gives the
# coefficients of the linear fit for each row of img.
beta = np.linalg.solve(A, Y)

# Create an array that holds the linear drift for each row.
# X has shape (n, 2) and beta has shape (2, m), so row_drift has shape (m, n),
# the same as img.
row_drift = X.dot(beta).T

# Remove the drift from img.
img2 = img - row_drift

答案 1 :(得分:2)

拟合一行是simple formula可直接使用,可以在numpy中完成约三条短线(下面的大多数代码只是制作和绘制数据并适合):

import numpy as np
import matplotlib.pyplot as plt

# make the data as sequential sections of a circle
theta = np.linspace(np.pi, 0, 120)
y = np.reshape(np.sin(theta), (10,12))
x = np.repeat(np.arange(12)[None,:], 10, axis=0)

# fit the line
m = lambda x: np.mean(x, axis=1)
beta = ( m(y*x) - m(x)*m(y) )/(m(x*x) - m(x)**2)
alpha = m(y) - beta*m(x)

# plot the data and fits
plt.plot([y[:,i] for i in range(12)], ".")  # plot the data
plt.gca().set_color_cycle(None) # reset the color cycle
fits = alpha[:,None] + beta[:,None]*x  # make lines from the fits for the plots
plt.plot(fits.T)
plt.show()

enter image description here