Pytorch 火炬-插值缺失值

Pytorch 火炬-插值缺失值,pytorch,interpolation,Pytorch,Interpolation,我有一组张量图像,形式为NumOfImagesxHxW,包括零。我正在寻找一种只使用同一图像中的信息(图像之间没有连接)插值缺失值(零)的方法。有没有办法用Pytork来做 F.插值似乎只适用于整形。我需要填充零,同时保持张量的维数和梯度 谢谢。编辑:事实证明,下面的内容不符合OP的要求,因为它没有为反向传播提供跟踪渐变的解决方案。仍然保留它,因为它可以作为解决方案的一部分使用 一种方法是将张量转换为numpy数组,并使用scipy插值,例如scipy.interpolate.LinearGri

我有一组张量图像,形式为NumOfImagesxHxW,包括零。我正在寻找一种只使用同一图像中的信息(图像之间没有连接)插值缺失值(零)的方法。有没有办法用Pytork来做

F.插值似乎只适用于整形。我需要填充零,同时保持张量的维数和梯度


谢谢。

编辑:事实证明,下面的内容不符合OP的要求,因为它没有为反向传播提供跟踪渐变的解决方案。仍然保留它,因为它可以作为解决方案的一部分使用

一种方法是将张量转换为numpy数组,并使用scipy插值,例如
scipy.interpolate.LinearGridInterpolator
或其他可能的numpy数组插值选项()。不确定这是否有帮助,因为这不是pytorch+可能需要复制周围的张量

由于scipy插值可能很慢,一种可能的解决方案是仅使用与缺失值相邻的像素进行插值(可以通过对缺失值掩码进行膨胀轻松获得)。我认为这可能会使速度提高一个数量级,这取决于张量的维数和缺失值的数量

编辑:实现了它,在我的例子中,它的速度似乎提高了两个数量级

def fillMissingValues(对于_interp,复制=真,
插值器=scipy.interpolate.LinearNDInterpolator):
将cv2、scipy、numpy作为np导入
如果是副本:
target_for_interp=target_for_interp.copy()
def GetPixelsForentERP(img):
"""
计算与无效值相邻的像素掩码-
用于插值。
"""
#屏蔽无效像素
无效的_mask=np.isnan(img)+(img==0)
kernel=cv2.getStructuringElement(cv2.morp_ELLIPSE,(3,3))
#展开以标记无效区域周围的边框
explated_mask=cv2.explate(无效的_mask.astype('uint8'),内核,
borderType=cv2.BORDER_常量,borderValue=int(0))
#具有有效像素掩码的像素级“和”(~无效的\u掩码)
屏蔽的\u用于\u interp=扩展的\u屏蔽*~无效的\u屏蔽
返回\u interp.astype('bool')的掩码,\u掩码无效
#用于插值的遮罩像素
遮罩\u用于\u interp,无效的\u遮罩=GetPixelsForentERP(目标\u用于\u interp)
#仅使用这些像素对孔进行插值
points=np.argwhere(为interp屏蔽)
值=针对\u interp的目标\u[针对\u interp的掩码\u]
插值器(点、值)
\u interp的目标\u[无效的\u掩码]=interp(np.argwhere(无效的\u掩码))
返回\u interp的目标\u
#对于目标张量:
target_filled=fillMissingValues(target.numpy().squence())
#转换回张量等。。

请注意,插值将在有效点的凸包外
np.nan
,如
LinearNDInterpolator
所述

EDIT:下面的答案不符合OP,因为它没有为反向传播提供跟踪渐变的解决方案。仍然保留它,因为它可以作为解决方案的一部分使用

一种方法是将张量转换为numpy数组,并使用scipy插值,例如
scipy.interpolate.LinearGridInterpolator
或其他可能的numpy数组插值选项()。不确定这是否有帮助,因为这不是pytorch+可能需要复制周围的张量

由于scipy插值可能很慢,一种可能的解决方案是仅使用与缺失值相邻的像素进行插值(可以通过对缺失值掩码进行膨胀轻松获得)。我认为这可能会使速度提高一个数量级,这取决于张量的维数和缺失值的数量

编辑:实现了它,在我的例子中,它的速度似乎提高了两个数量级

def fillMissingValues(对于_interp,复制=真,
插值器=scipy.interpolate.LinearNDInterpolator):
将cv2、scipy、numpy作为np导入
如果是副本:
target_for_interp=target_for_interp.copy()
def GetPixelsForentERP(img):
"""
计算与无效值相邻的像素掩码-
用于插值。
"""
#屏蔽无效像素
无效的_mask=np.isnan(img)+(img==0)
kernel=cv2.getStructuringElement(cv2.morp_ELLIPSE,(3,3))
#展开以标记无效区域周围的边框
explated_mask=cv2.explate(无效的_mask.astype('uint8'),内核,
borderType=cv2.BORDER_常量,borderValue=int(0))
#具有有效像素掩码的像素级“和”(~无效的\u掩码)
屏蔽的\u用于\u interp=扩展的\u屏蔽*~无效的\u屏蔽
返回\u interp.astype('bool')的掩码,\u掩码无效
#用于插值的遮罩像素
遮罩\u用于\u interp,无效的\u遮罩=GetPixelsForentERP(目标\u用于\u interp)
#仅使用这些像素对孔进行插值
points=np.argwhere(为interp屏蔽)
值=针对\u interp的目标\u[针对\u interp的掩码\u]
插值器(点、值)
\u interp的目标\u[无效的\u掩码]=interp(np.argwhere(无效的\u掩码))
返回\u interp的目标\u
#对于目标张量:
target_filled=fillMissingValues(target.numpy().squence())
#转换回张量等。。

请注意,插值将在有效点的凸包外
np.nan
,如
LinearNDInterpolator
所述

如果只需要最近邻插值,则可以通过返回索引映射而不是插值图像来进行微分

我所做的是从
scipy.interpolate.NearestNDInterpolator
创建一个新类,并重写它的
\u调用
方法。它只是返回索引而不是值

from scipy.interpolate.interpnd import _ndim_coords_from_arrays

class NearestNDInterpolatorIndex(NearestNDInterpolator):
    def __init__(self, x, y, rescale=False, tree_options=None):
        NearestNDInterpolator.__init__(self, x, y, rescale=rescale, tree_options=tree_options)
        self.points = np.asarray(x)

    def __call__(self, *args):
        """
        Evaluate interpolator at given points.
        Parameters
        ----------
        xi : ndarray of float, shape (..., ndim)
            Points where to interpolate data at.
        """
        xi = _ndim_coords_from_arrays(args, ndim=self.points.shape[1])
        xi = self._check_call_shape(xi)
        xi = self._scale_x(xi)
        dist, i = self.tree.query(xi)
        return self.points[i]
然后,在
fillMissingValues
中,我们不返回
target\u for_interp
,而是返回以下内容:

source_indices = np.argwhere(invalid_mask)
target_indices = interp(source_indices)

return source_indices, target_indices
将新的插值器传递给
fillMissin
img[..., source_indices[:, 0], source_indices[:, 1]] = img[..., target_indices[:, 0], target_indices[:, 1]]