在Python中,如何高效计算二维数组滑动窗口的众数?

3 投票
2 回答
813 浏览
提问于 2025-04-17 12:44

我有一张RGBA格式的图片,想要放大它,同时保持图像的平滑度。

问题是我需要保持颜色完全不变(背景:我在调整一张省份用颜色编码的地图),所以我不能仅仅使用双三次插值来调整大小,因为那样会在平滑的同时也改变像素的颜色。

因此,为了得到平滑的边缘,我希望先用最近邻算法放大(这样会产生阶梯状的图案),然后通过用某个半径内出现频率最高的像素颜色来替换目标图像中的每个像素,像这样:

from PIL import Image, ImageFilter
amount=3
image=Image.open(<file>)
image=image.filter(ImageFilter.ModeFilter(amount))

这个过程完成得相当快,但问题是它不奏效,因为PIL的图像滤镜是分别对每个通道操作的。真是让人生气

我尝试使用numpy数组,并在循环中做以下操作:

dest[x,y]=Counter([tuple(e) for e in reshape(source[max(x-r,0):x+r+1,max(y-r,0):y+r+1],(-1,4))]).most_common()[0][0]

注意这里的dest和source是相同形状的XxYx4数组,因此需要进行必要的重塑和转换成元组。
理论上这样是可行的,但对于我正在处理的8200万像素的图像来说,完成这个过程需要12个小时。我推测这主要是因为在转换和重塑时产生了不必要的开销。

在Python中,做这个任务的合适方法是什么?

我快要放弃了,准备写一个C++模块来完成这个任务。
任何能让我避免走这条路的建议都非常感谢!

2 个回答

-1

EPX在图像缩放中提到,它不会引入新的颜色。比如,2倍缩放的效果是这样的:

  A    --\ 1 2
C P B  --/ 3 4
  D 

IF C==A => 1=A
IF A==B => 2=B
...

而3倍缩放的效果也在那里面有描述。
除此之外,我同意“直接用C语言”这个说法——这要看你已经掌握了什么知识。 有没有人用过np_inline

1

如果你想在图片中使用固定的一组颜色,那么“调色板”模式可能更合适(至少在你的图片中颜色不超过256种的情况下)。

我建议你先把图片转换成“P”模式(因为我对PIL不太熟悉,所以不太确定这有多简单。也许你需要先手动创建调色板?)然后再应用模式过滤器。

我想到的另一个解决办法是,在放大图片时使用双三次插值,然后再用从原始图片中提取的调色板转换成调色板图片。这样可能会比你现在的方法效果更好,也更容易实现。

撰写回答