我有一个表示图像的2D numpy数组(请参见下文)。python - 从2d numpy数组中提取旋转1d轮廓的结果不一致-LMLPHP

图像中的椭圆对象从垂直y轴旋转角度theta。在我的代码中,我想测量物体在各个位置的FWHM(包括通过最大化的半长轴以theta角)。

为此,我使用了这两个问题的技术(以给定角度提取线,然后使用UnivariateSpline来计算给定的1d轮廓的FWHM):How to extract an arbitrary line of values from a numpy array?Finding the full width half maximum of a peak

但是,我注意到我的结果不一致。如果我从整个图像(是(641,641)阵列)中以给定角度提取轮廓,则与从(100,100)子图像中以相同角度获得轮廓相比,FWHM会得到不同的结果对象居中的位置。我意识到,由于该方法涉及插值,因此可能会在轮廓上得到不同的值。但是我需要的是一种可靠且一致的方法来计算这些FWHM,以及将其最大化的角度(因为现在,它为我提供了子图像与整个图像不同的角度)。这是我的代码:

import numpy as np
from scipy.interpolate import UnivariateSpline

def profiles(image, theta):
    max_y, max_x = np.where(image==1) #the image has been normalized so that the highest intensity point=1
    max_y, max_x = max_y[0], max_x[0]

    subimage = image[max_y-50:max_y+50, max_x-50:max_x+50] # now the maximum is exactly centered at (50, 50)

    # Set up to extract profiles (do two legs to ensure it passes through centroid)
    x_maj_1, y_maj_1 = 50-50*np.tan(theta), 0
    mid_x, mid_y = 50, 50
    x_maj_2, y_maj_2 = 50+50*np.tan(theta), 99

    # Form axes
    length_maj = int(round(np.hypot(x_maj_2-x_maj_1, y_maj_2-y_maj_1)))
    x1, y1 = np.linspace(x_maj_1, mid_x, length_maj//2), np.linspace(y_maj_1, mid_y, length_maj//2)
    x2, y2 = np.linspace(mid_x, x_maj_2, length_maj//2)[1:], np.linspace(mid_y, y_maj_2, length_maj//2)[1:]

    # Concatenate legs
    x_maj = np.concatenate((x1, x2), axis=0)
    y_maj = np.concatenate((y1, y2), axis=0)

    # Get profile
    z_maj = subimage[y_maj.astype(np.int), x_maj.astype(np.int)]
    return z_maj

def interpolate_width(axis):
    half_max = 1/2
    x = np.arange(0, len(axis))
    spline = UnivariateSpline(x, axis-half_max, s=0)
    r1, r2 = spline.roots()
    return r2-r1 #FWHM in pixel units


现在,要从FWHM最大化的y轴找到角度:

thetas = np.arange(0, 45, 0.5)
widths = []
for theta in thetas:
    theta = np.deg2rad(theta)
    z = profiles(image, theta)
    width = interpolate_width(z)
    widths.append(width)

fwhm_maj = max(widths)
angle_arg = np.array(widths).argmax()
angle_max = thetas[angle_arg]
print('Maximized FWHM and associated position angle:', fwhm_maj, angle_max)


输出:Maximized FWHM and associated position angle: 20.899 14.5

根据我链接的网站上的信息,图像的像素比例为0.275弧秒。因此,乘以该值,FWHM应该在14.5度的位置角处达到最大值,其值约为5.75弧秒。但是,网站上的表1清楚地表明,与y轴的最大位置角度仅为6度,而主轴的FWHM为7.36弧秒。因此,这里一定有问题。

如果我再次运行此代码,但在整个图像而不是子图像上运行,则角度和FWHM会得到完全不同的结果。有谁知道我如何找到更一致(更准确)的方法?谢谢!

最佳答案

不确定100%,但是您似乎将线坐标捕捉到像素网格上,这对我来说确实不准确。另外,“倒置信箱”(白条)可能会使您的程序感到困惑?也许使用正确的2D插值并裁剪图像会更安全,如下所示:

import numpy as np
from scipy import ndimage, interpolate, optimize

img = ndimage.io.imread('VJQwQ.png')
# b&w
img = img[..., 0]
# cut "white letterbox"
img = img[:, np.where(np.any(img!=255, axis=0))[0]]

# setup interpolator for off grid pixel values
x, y = img.shape
x, y = (np.arange(z) - (z-1)/2 for z in (x, y))
intr = interpolate.RectBivariateSpline(x, y, img, kx=3, ky=3)
s = np.arange(-50, 51)

# setup line sections
# for simplicity we assume the peak is in the center
def at_angle(phi):
    def f(s, shift=0):
        x, y = np.cos(phi)*s, np.sin(phi)*s
        return intr(x, y, grid=False) - shift
    return f

# example
phi = np.pi/3
f = at_angle(phi)
mx = f(0)
left = optimize.brentq(f, -50, 0, (mx/2,))
right = optimize.brentq(f, 0, 50, (mx/2,))

# plot it
from matplotlib import pylab
pylab.plot(s, f(s))
pylab.plot([left, left], [0, mx])
pylab.plot([right, right], [0, mx])
pylab.plot([-50, 50], [mx/2, mx/2])
pylab.savefig('tst.png')


python - 从2d numpy数组中提取旋转1d轮廓的结果不一致-LMLPHP

关于python - 从2d numpy数组中提取旋转1d轮廓的结果不一致,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52451102/

10-12 21:38