[英]Inconsistent results from extracting rotated 1d profiles from 2d numpy array
图像中的椭圆形对象从垂直 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.