繁体   English   中英

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

[英]Inconsistent results from extracting rotated 1d profiles from 2d numpy array

我有一个代表图像的 2D numpy 数组(见下文)。 频段 3 的中央 PSF:http://wise2.ipac.caltech.edu/docs/release/allsky/expsup/sec4_4c.html#rchisqind

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

为此,我使用了来自这两个问题的技术(以给定的角度提取线,然后使用 UnivariateSpline 计算给定 1d 轮廓的 FWHM): 如何从 numpy 数组中提取任意线值? 找到峰的半峰全宽

但是,我注意到我的结果不一致。 如果我从整个图像(这是一个 (641, 641) 数组)中以给定角度提取轮廓,我得到的 FWHM 结果与从 (100,100) 子图像中以相同角度获取轮廓的结果不同对象居中的位置。 我意识到由于该方法涉及插值,因此我可能会沿配置文件获得不同的值。 但我需要的是一种可靠且一致的方法来计算这些 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')

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM