下面是一段代码,目标是从图像中删除像素。我是python新手,我不确定这是否是正确的解决方案。我提出的解决方案是将阵列转换为二维列表,并删除每个像素(我尝试了np.delete,但它一直抱怨阵列必须是矩形的),然后返回到阵列,然后返回到图像,如下所示
import numpy as np
from PIL import Image
def removeSeam(image, seam):
"""
image: numpy array representing a PIL image
seam: list of pixel coords represented as tuples in the form (x, y)
returns a PIL image
"""
grid = image.tolist()
for i in range(len(seam)):
grid[i].pop(seam[i][1])
return Image.fromarray(np.array(grid))
当我运行类似这样的操作时会引发错误(可追溯到函数中的return语句):
example = np.array([
[[255, 255, 255], [0, 0, 0], [255, 255, 255]],
[[0, 0, 0], [255, 255, 255], [0, 0, 0]],
[[255, 255, 255], [0, 0, 0], [255, 255, 255]]])
# this seam should remove the top left, center, and bottom left pixels
seam = [(0, 0), (1, 1), (0, 2)]
removeSeam(example, seam)
从数组到列表的转换很少有必要,而且总是很昂贵。数组将数据打包到一个连续的缓冲区中,但列表将每个元素打包到一个单独的对象中,并保留指向这些对象的指针。这也意味着数组可以很容易地作为整个单元处理,而列表中的每个对象都需要独立处理。因此,您几乎不想使用列表来处理图像
只要保证seam从每行中删除一个元素,就可以使用以下步骤删除它:
(r, c, 3)
数组视为(r * c, 3)
数组。这不涉及复制任何数据李>(r, c - 1, 3)
。这也不会复制任何数据李>我建议您更新代码,以支持行或列的索引接缝,并支持
axis
参数remove_seam
。这样,您只需要传入一个数组(包括一个列表),该数组与正在移动的轴的大小相匹配:这看起来可能比您现有的函数长得多,但它只执行一个稍微昂贵的操作:
np.delete(image, seam)
,并且尽可能便宜地执行。如果你仔细看一下其他的操作,它们只是将非常小的数字列表混在一起,以获得正确的形状和步幅以下是为新接口重写的示例:
这将删除左上、中和左下像素。如果要设置
axis=1
,则需要删除左上、中和右上像素:要将数组转换为映像,需要将其转换为
np.uint8
数据类型。有几种方法可以做到这一点。一种方法是输入正确的大小:另一种方法是转换输出:
最后一种方法是将输出视为
np.uint8
,但您必须非常小心地执行此操作,包括注意输出的endianness:相关问题 更多 >
编程相关推荐