我需要用Alpha透明度替换PNG图像中的所有白色(ish)像素。
我在AppEngine中使用Python,因此无法访问像PIL,imagemagick等库.AppEngine确实有一个图像库,但主要是调整图像大小。
我找到了优秀的小pyPNG module,并成功完成了一项能够满足我需要的功能:
主循环的伪代码类似于:
for each pixel:
if pixel looks "quite white":
set pixel values to transparent
otherwise:
keep existing pixel values
和(假设8位值)“相当白”将是:
where each r,g,b value is greater than "240"
AND each r,g,b value is within "20" of each other
这是我第一次以这种方式处理原始像素数据,虽然有效,但它的表现也非常糟糕。似乎必须有一种更有效的方式处理数据而不以这种方式迭代每个像素? (矩阵?)
我希望有更多处理这些事情经验的人可以指出我算法中一些更明显的错误/改进。
谢谢!
答案 0 :(得分:1)
老实说,我能想到的唯一一种启发式方法就是在你的图像上选择一些任意的随机点并使用flood fill。
这只适用于你的图像是大的连续白色部分(如果你的图像是背景前没有或没有小孔的物体,那么你很幸运 - 你实际上有一个启发式指针洪水填充来自。)
(免责声明:我不是形象大师= /)
答案 1 :(得分:1)
这仍会访问每个像素,但可能更快:
new_pixels = []
for row in pixels:
new_row = array('B', row)
i = 0
while i < len(new_row):
r = new_row[i]
g = new_row[i + 1]
b = new_row[i + 2]
if r>threshold and g>threshold and b>threshold:
m = int((r+g+b)/3)
if nearly_eq(r,m,tolerance) and nearly_eq(g,m,tolerance) and nearly_eq(b,m,tolerance):
new_row[i + 3] = 0
i += 4
new_pixels.append(new_row)
它避免了切片生成器,它将复制每个像素的整行像素(每次少于一个像素)。
它还通过直接复制输入行预先分配输出行,然后只写入已更改的像素的alpha值。
更快的是根本不分配一组新的像素,只是直接写在源图像中的像素上(假设你不需要源图像)。
答案 2 :(得分:0)
我很确定没有这方面的捷径。你必须访问每个像素。
答案 3 :(得分:0)
这个问题似乎与Python中的循环有关,而不是与图像有关。
Python循环非常慢,最好避免它们并使用内置循环运算符。
在这里,如果您愿意复制图像,可以使用列表理解:
def make_transparent(pixel):
if pixel looks "quite white": return transparent
else: return pixel
newImage = [make_transparent(p) for p in oldImage]