0

我正在使用 size 的图像512x512。使用einops补丁大小为32. 总体而言,补丁的数量是256,换句话说,我们得到了一个大小为 的新“图像” 256x1024

由于该图像实际上是分割问题的掩码,因此该图像实际上仅包含 4 个值(4 类):0用于背景、1用于第一类、2用于第二类、3用于第三类。

我的目标是获取每个补丁,并为每个类计算C以下内容:

此补丁中的像素数/标记的像素数C

这应该给我一个大小为 4 的数组,其中第一个条目是补丁中的像素总数(1024)超过背景像素数(标记为 0),第二个、第三个和第四个条目是相同的,但对于对应的类。

理论上,我知道我需要遍历每个补丁,然后计算当前补丁中每个类的像素数,然后除以1024. 这样做256正是我想要的。问题是我有(非常)大量的图像需要为此执行此操作,并且大小512只是使问题更简单的一个示例,因此 for 循环是不可能的。

我知道我可以使用 numpy 得到我想要的结果。我都试过了:numpy.apply_over_axesnumpy.apply_along_axis我不知道哪一个更适合这项任务,还有numpy.where一个我不知道它是如何应用在这里的。

这是我所做的:

from einops import rearrange
import numpy as np

labn = np.random.randint(4,size= (512,512))      # Every pixels in this image is of value: 0,1,2,3
to_patch = rearrange(labn, "(h p1) (w p2) -> (h w) (p1 p2)", p1=32, p2=32)
print(to_patch.shape) # (256,1024)

c0 = np.full(1024, 0)
c1 = np.full(1024, 1)
c2 = np.full(1024, 2)
c3 = np.full(1024, 3)

def f(a):
    _c0 = a == c0
    _c1 = a == c2
    _c2 = a == c2
    _c3 = a == c3
    pr = np.array([np.sum(_c0), np.sum(_c1), np.sum(_c2), np.sum(_c3)]) / 1024
    return pr

resf = np.apply_along_axis(f, 1, to_patch)
print(resf.shape) # (256, 4, 1024)

两件事情:

  1. 我希望输出是256x4沿第二个轴的每个数组总和为 1 的位置。
  2. 有没有更快/更好/pythonic的方法来做到这一点,最好是矢量化的?

编辑:我忘了加总和,所以现在我得到了256x4.

4

1 回答 1

1

有一个内置的函数来计算出现次数torch.histc,它类似于 Python 的collections.Counter.

torch.histc(input, bins=100, min=0, max=0, *, out=None) → Tensor
计算张量的直方图。

元素被分类到 和 之间的等宽箱minmax。如果 minmax都为零,则使用数据的最小值和最大值。

低于min和高于的元素max将被忽略。

你需要指定数量bins,这里是类的数量C。以及用于排序的minmax值。此外,它不适用于多维张量,因此生成的张量将包含输入张量的全局统计信息,而与维度无关。作为一种可能的解决方法,您可以遍历补丁,torch.histc每次调用,然后堆叠结果并标准化:

resf = torch.stack([torch.histc(patch, C, min=0, max=C-1) for patch in x]) / x.size(1)
于 2021-09-08T20:01:48.283 回答