极坐标重新投影为笛卡尔网格
我有一个极坐标网格(r, theta),也就是说每个单元格是一个环形区域,里面包含一些物理量的数值(比如温度)。我想把这些数值重新整理到一个笛卡尔坐标网格上。有没有什么Python的工具可以做到这一点?
我并不想把单元格中心的坐标从极坐标转换成笛卡尔坐标——这很简单。相反,我是在寻找一个可以真正正确地重新整理数据的工具。
谢谢大家的建议!
6 个回答
4
OpenCV 3.4现在可以很简单地实现这个功能,使用的是warpPolar()这个函数。
调用起来非常简单:
import numpy as np
import cv2
from matplotlib import pyplot as plt
# Read in our image from disk
image = cv2.imread('washington_quarter.png',0)
plt.imshow(image),plt.show()
margin = 0.9 # Cut off the outer 10% of the image
# Do the polar rotation along 1024 angular steps with a radius of 256 pixels.
polar_img = cv2.warpPolar(image, (256, 1024), (image.shape[0]/2,image.shape[1]/2), image.shape[1]*margin*0.5, cv2.WARP_POLAR_LINEAR)
# Rotate it sideways to be more visually pleasing
polar_img = cv2.rotate(polar_img, cv2.ROTATE_90_COUNTERCLOCKWISE)
plt.imshow(polar_img),plt.show()
7
我之前也遇到过类似的问题,想把极坐标数据转换成笛卡尔坐标网格,反过来也一样。这里提供的解决方案效果不错,但坐标转换的时间有点长。我想分享一个不同的方法,可以把处理时间缩短到原来的50倍甚至更多。
这个算法使用了 scipy.ndimage.interpolation.map_coordinates
这个函数。
我们来看一个简单的例子:
import numpy as np
# Auxiliary function to map polar data to a cartesian plane
def polar_to_cart(polar_data, theta_step, range_step, x, y, order=3):
from scipy.ndimage.interpolation import map_coordinates as mp
# "x" and "y" are numpy arrays with the desired cartesian coordinates
# we make a meshgrid with them
X, Y = np.meshgrid(x, y)
# Now that we have the X and Y coordinates of each point in the output plane
# we can calculate their corresponding theta and range
Tc = np.degrees(np.arctan2(Y, X)).ravel()
Rc = (np.sqrt(X**2 + Y**2)).ravel()
# Negative angles are corrected
Tc[Tc < 0] = 360 + Tc[Tc < 0]
# Using the known theta and range steps, the coordinates are mapped to
# those of the data grid
Tc = Tc / theta_step
Rc = Rc / range_step
# An array of polar coordinates is created stacking the previous arrays
coords = np.vstack((Ac, Sc))
# To avoid holes in the 360º - 0º boundary, the last column of the data
# copied in the begining
polar_data = np.vstack((polar_data, polar_data[-1,:]))
# The data is mapped to the new coordinates
# Values outside range are substituted with nans
cart_data = mp(polar_data, coords, order=order, mode='constant', cval=np.nan)
# The data is reshaped and returned
return(cart_data.reshape(len(y), len(x)).T)
polar_data = ... # Here a 2D array of data is assumed, with shape thetas x ranges
# We create the x and y axes of the output cartesian data
x = y = np.arange(-100000, 100000, 1000)
# We call the mapping function assuming 1 degree of theta step and 500 meters of
# range step. The default order of 3 is used.
cart_data = polar_to_cart(polar_data, 1, 500, x, y)
希望这个信息能帮助到和我有相同困扰的人。
12
谢谢大家的回答 - 在多想了一下之后,我写出了下面的代码:
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as mpl
from scipy.interpolate import interp1d
from scipy.ndimage import map_coordinates
def polar2cartesian(r, t, grid, x, y, order=3):
X, Y = np.meshgrid(x, y)
new_r = np.sqrt(X*X+Y*Y)
new_t = np.arctan2(X, Y)
ir = interp1d(r, np.arange(len(r)), bounds_error=False)
it = interp1d(t, np.arange(len(t)))
new_ir = ir(new_r.ravel())
new_it = it(new_t.ravel())
new_ir[new_r.ravel() > r.max()] = len(r)-1
new_ir[new_r.ravel() < r.min()] = 0
return map_coordinates(grid, np.array([new_ir, new_it]),
order=order).reshape(new_r.shape)
# Define original polar grid
nr = 10
nt = 10
r = np.linspace(1, 100, nr)
t = np.linspace(0., np.pi, nt)
z = np.random.random((nr, nt))
# Define new cartesian grid
nx = 100
ny = 200
x = np.linspace(0., 100., nx)
y = np.linspace(-100., 100., ny)
# Interpolate polar grid to cartesian grid (nearest neighbor)
fig = mpl.figure()
ax = fig.add_subplot(111)
ax.imshow(polar2cartesian(r, t, z, x, y, order=0), interpolation='nearest')
fig.savefig('test1.png')
# Interpolate polar grid to cartesian grid (cubic spline)
fig = mpl.figure()
ax = fig.add_subplot(111)
ax.imshow(polar2cartesian(r, t, z, x, y, order=3), interpolation='nearest')
fig.savefig('test2.png')
这虽然不算是严格的重新网格化,但对于我需要的功能来说效果很好。发这段代码是希望对其他人有帮助。如果你有改进的建议,欢迎提出!