【问题标题】:Quickly Plotting Polar Radar Data using Python?使用 Python 快速绘制极地雷达数据?
【发布时间】:2019-12-06 22:41:22
【问题描述】:

我有一个有趣的应用程序,它需要将 3D 极坐标数据(该点的角度、距离和值)转换为表示数据的图像。这是我在自定义应用程序中使用的 NOAA NEXRAD 雷达数据。

数据存储在 3 个数组中,range_data(与雷达的距离,以米为单位,1800 个点)、azimuth_data(以 0.5 度为单位的角度,720 个点)和radar_data(一个 720x1800 的数组,每个数组包含一个数据值)距离和方位角的组合)。这是我从 NOAA 获取数据的格式,所以我无法在这方面做太多改变。

现在,我正在使用 matplotlib pcolormesh 按以下方式绘制它(基本上是this example from the library I'm using):

x = range_data * np.sin(np.deg2rad(azimuth_data))[:,None]
y = range_data * np.cos(np.deg2rad(azimuth_data))[:,None]

fig, ax = plt.subplots(1,1,figsize=(4,4))
ax.pcolormesh(x,y,radar_data,cmap=ref_cmap,norm=ref_norm)
ax.set_aspect('equal','datalim')
ax.set_xlim(-460, 460)
ax.set_ylim(-460, 460)
ax.set_axis_off()
plt.axis('off')

plt.savefig(imgpath, bbox_inches='tight', transparent=True, dpi=dpiCalc)

目前的主要问题是使用 savefig() 命令实际渲染和保存绘图。每张图像大约需要 7 秒,处理 20 组左右的数据对于我心目中的应用程序来说需要的时间太长了。

由于我只需要颜色映射的数据作为图像,因此我并不真正需要 matplotlib 的大多数工具和功能。我在想一定有一种更快的方法可以从我的原始数据中生成这张图片。

我尝试逐步遍历数据并逐个填充 x-y 数组,然后使用 PIL 保存数组,但手动迭代数据所用的时间甚至比 matplotlib 还要长。使用 numpy 进行数组操作会更快,但我真的想不出任何操作来转换坐标系之间的数据。

为了更简单地分解问题,我将极坐标数据以 value[角度,距离] 格式存储在 720x1800 雷达数据数组中,我想在最快的方法。由于我既不是程序员也不是数学家,所以我可能忽略了一些简单的事情。

感谢任何和所有建议!

【问题讨论】:

    标签: python matplotlib image-processing


    【解决方案1】:

    我认为你本质上想要做一个极坐标失真,转换这个:

    进入这个:

    我在终端中使用 ImageMagick 做到了这一点,因为它既简单又快速,可以安装在大多数 Linux 发行版上,并且适用于 macOS 和 Windows。我使用的命令是:

    magick image.png -virtual-pixel Black -distort Polar 0 result.png
    

    注意:如果您使用的是 ImageMagick v6,请将上述命令中的 magick 替换为 convert

    注意:如果您想进行实验,我制作了这样的初始图像:

    magick -size 1800x720  gradient:red-blue image.png 
    

    如果这是您想要的,您可以在 Python 中使用多种工具中的任何一种来实现:

    • skimage - warp_polar()
    • OpenCV - warpPolar()
    • 魔杖 - distort()

    或者你可以“shell out”到我上面使用的 ImageMagick 命令。

    关键字:Python、图像处理、极坐标、去极坐标、笛卡尔坐标、变换、雷达、绘图

    【讨论】:

    • 我真的很喜欢这个答案。在我的搜索过程中,我在一些示例中看到了您在上面显示的从笛卡尔到极坐标的映射,但无论出于何种原因,它都没有准确地点击正在发生的事情。我唯一还在苦苦挣扎的是图像转换的细节。现在我正在以毫秒为单位生成一个漂亮的笛卡尔图,但我正试图弄清楚如何将该图像从 PIL 移动到 skimage 以进行转换。
    • Skimage 与 Numpy 数组一起使用,因此您可以使用 skimage = np.array(PILImage) 从 PIL 图像制作 skimage 您可能希望使其浮动并除以 255。
    • 我的问题实际上只是没有意识到 warp_polar 只有在您告诉它专门接受 3D 阵列时才能在 3D 阵列上运行。现在我只是在使用 origin 和 radius 参数来从 warp_polar 获取可用的图像,因为它现在没有表现。
    • 如果你有一些你想要的代码,你可以随时提出一个新问题并使用我的示例图像。
    【解决方案2】:

    Matplotlib 不是一个好的解决方案。

    • Vispy

      OpenGL 支持的绘图。界面不是那么精致,但很多功能已经可用。只需点击examples 并尝试找到您不必编写 GLSL 的函数(不在文件夹“gloo”中但在“plot”或“scene”中的函数)。

    • PyQtGraph

      适用于实时绘图,但目前未维护。仅限 Qt4。

    • PyQwt

      也无人维护。仅限 Qt4。

    您也可以在不做太多工作的情况下组装一个自定义 GUI,周围有很多示例。例如here。只需寻找“实时绘制 Qt”。

    【讨论】:

      【解决方案3】:

      值得注意的是,以下代码对我来说需要 1 秒:

      import numpy as np
      import matplotlib.pyplot as plt
      import time
      
      t = time.time()
      range_data = np.arange(1800)
      azimuth_data = np.linspace(0, 359.5, 720)
      radar_data = np.dot(np.atleast_2d(azimuth_data).T , np.atleast_2d(range_data))
      
      x = range_data * np.sin(np.deg2rad(azimuth_data))[:,None]
      y = range_data * np.cos(np.deg2rad(azimuth_data))[:,None]
      
      fig, ax = plt.subplots(1,1,figsize=(4,4))
      ax.pcolormesh(x,y,radar_data)
      ax.set_aspect('equal','datalim')
      
      ax.set_axis_off()
      
      plt.savefig("radar.png", transparent=True, dpi=100)
      print(time.time()-t)
      

      如果将分辨率减半,即 900 x 360 点而不是 1800 x 720,则只需 0.3 秒。所以这也主要是你想要获得多大的图像的问题。

      【讨论】:

      • 这可能是处理能力的问题。我使用的 DPI 是 900,所以这绝对是它比您的示例花费更长的时间的原因之一。遗憾的是,我正在为其开发的应用程序将在低功耗笔记本电脑和移动设备上运行,这意味着 matplotlib 无法为我做更多的事情。感谢您的建议。
      • 笔记本电脑的标准屏幕分辨率最大为1020p。这意味着(a)图形大小乘以 dpi 不应超过 1000。(b)范围分辨率不应超过 1020/2。上面的一切都将被浪费。将其插入将导致 0.35 秒。
      【解决方案4】:

      我假设您已经这样做了,只是为了确定: 如果你的 azimuth_data 不是一个 numpy 数组,你可能会失去性能。

      【讨论】:

        猜你喜欢
        • 2018-05-22
        • 1970-01-01
        • 2021-07-31
        • 1970-01-01
        • 1970-01-01
        • 2020-05-01
        • 1970-01-01
        • 2018-03-11
        • 1970-01-01
        相关资源
        最近更新 更多