【问题标题】:Calculate field of view from a depth map从深度图计算视野
【发布时间】:2021-01-14 20:44:24
【问题描述】:

我有一个深度 numpy n*n 数组。其中每个单元格的值代表该单元格的高度。我想计算视野。换句话说:

if Pixel_height > viewer_height:
    pixels_behind = -1

有没有简单的方法可以做到这一点?

编辑:要清楚,我想创建一个类似于这个绿色蒙版的位置矩阵,知道我们有一个高度矩阵 n*m enter image description here

【问题讨论】:

  • 请更具体一点。你会得到什么作为输入?除了高度图和查看器高度之外,您会得到类似(row, column) 对指示查看器位置的东西吗?还是总是假定观看者处于高度图之外的某个点?
  • 从你的描述来看应该和pixel_height[pixel_height > viewer_height] = -1一样简单。但是,正如@jdehesa 所提到的,也许您可​​以将您的问题重新表述得更准确一些。也许有一个示例数组和预期的输出?
  • 我也不确定你的逻辑是否正确......如果某个像素的高度为a,而查看器的高度为h < a,但紧随其后的像素的高度为b > a ,那么那也不应该是可见的吗?也就是说,当你面前有一座山时,你可以看到它的顶部,而不仅仅是看到它比你还高的地方。
  • 对不起,你是对的,也许它有点不清楚。假设查看器始终位于固定的行和列中。是的(行,列)代表位置。并且观看者总是处于相同的姿势。我想要的也得到这些像素后面的投影。所以如果前面的像素超过了这个限制,那么后面的像素值也是 = -1
  • @user3885334 那么我的建议能解决你的问题吗?

标签: python numpy opencv computer-vision point-clouds


【解决方案1】:

我想出了这个功能,它不是很完美,但做的事情和你说的差不多。它有一个resolution 参数,表示您要考虑的圆周上有多少个“角度步长”。我不确定这是解决这个问题的“正确”方法,而且我觉得应该有更聪明的方法来做一些操作,但无论如何。

import numpy as np

def view_field(height_map, viewer_height, viewer_pos, resolution=360):
    height_map = np.asarray(height_map)
    h, w = height_map.shape
    vi, vj = viewer_pos
    # Find locations higher than viewer
    m = height_map > viewer_height
    # Find angle of each pixel relative to viewer
    ii, jj = np.ogrid[-vi:h - vi, -vj:w - vj]
    a = np.arctan2(ii, jj)
    # Distance of each pixel to viewer
    d2 = np.square(ii) + np.square(jj)
    d = np.sqrt(d2)
    # Find angle range "behind" each pixel
    pix_size = 0.5
    ad = np.arccos(d / np.sqrt(d2 + np.square(pix_size)))
    # Minimum and maximum angle encompassed by each pixel
    amin = a - ad
    amax = a + ad
    # Define angle "bins"
    ar = np.linspace(-np.pi, np.pi, resolution + 1)
    # Find the bin corresponding to each pixel
    b = np.digitize(a, ar) % resolution
    bmin = np.digitize(amin, ar) % resolution
    bmax = np.digitize(amax, ar) % resolution
    # Find the closest distance to a high pixel for each angle bin
    angdist = np.full_like(ar, np.inf)
    np.minimum.at(angdist, bmin[m], d[m])
    np.minimum.at(angdist, bmax[m], d[m])
    # Visibility is true if the pixel distance is less than the
    # visibility distance for its angle bin
    return d <= angdist[b]

接下来是这样的:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# A wavy function for testing
def ackley(x, y):
    return (-20 * np.exp(-0.2 * np.sqrt(0.5 * (np.square(x) + np.square(y))))
            - np.exp(0.5 * (np.cos(2 * np.pi * x) + np.cos(2 * np.pi * y)))
            + np.e + 20)

# Make input data
x, y = np.ogrid[-4:4:100j, -4:4:100j]
height_map = ackley(x, y)
viewer_height = 7.5
# Viewer coordinates are in "pixel space"
viewer_pos = (50, 70)
# Compute visibility
f = view_field(height_map, viewer_height, viewer_pos)
# Plot height map and result
plt.figure(figsize=(8, 4))
ax = plt.subplot(121, projection='3d')
ax.plot_surface(np.arange(100)[:, np.newaxis], np.arange(100),
                height_map, color='b', alpha=0.6)
ax.scatter3D(*viewer_pos, viewer_height, s=5, c='r', label='Viewer')
plt.title('Height map')
plt.legend()
plt.subplot(122)
plt.imshow(f)
plt.title('Visibility map')
plt.tight_layout()

以及由此产生的情节:

【讨论】:

  • 我实现了它。实际上看起来非常好。我确实将 pix_size 设置为零,它似乎仍然工作得很好。我这样想,不将值转换为角度可以提高准确性。
  • @user3885334 我想这取决于您的高度图的分辨率和平滑度。具有相对高分辨率且不太嘈杂的地图应该不会带来太大的麻烦。如果它适合您将pix_size 设置为零(这是合理的,我在决定分箱解决方案之前考虑了整个pix_size / amin / amax 事情,但它可能不是那么有用) ,你显然可以跳过ad,只做np.minimum.at(angdist, b[m], d[m])来计算angdist。随意发布您能想到的任何其他解决方案,无论是否源自此解决方案。
猜你喜欢
  • 2020-01-26
  • 2013-10-25
  • 2017-02-15
  • 2015-02-27
  • 1970-01-01
  • 2022-11-21
  • 2016-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多