问题是你必须考虑许多不同的情况。
- 8 位 R、G、B、A 图像(这显然是你最初拥有的)
- 8 位 R、G、B 图像
- 8 位灰度级
- 8 位索引图像
对于 8 位灰度级,像素不是 4-uplets (R,G,B,A) 而是数字。因此,sum(x) 应替换为 x。然后你可以期望它值 255,而不是 255*4 白色(但这也不是确定的。也有一些 'MINISWHITE' 格式。因为我没有例子,而且对 PIL 不是很熟悉(你显然正在使用),不能确定 PIL 是否会使它透明(我的意思是,如果它会在加载时转换它)。
例如在你的代码的第一部分
white_lines = 0
for line in pixels:
white_count = sum([x for x in line]) - im.width * 255
if (white_count) == 0:
white_lines += 1
else:
break
对于 R、G、B 图像,您的代码就可以了,但是当总和为 255*4 时,白色不是,而是 255*3。
您的第二个示例是索引图像。所以 8 位,但无论如何都是颜色。
通过将其转换为“L”,即灰度级,您得到了您所抱怨的。
因此,这里的简单答案是建议您将所有内容转换为RGB 或RGBA,然后使用您的代码。
for f in pa_files:
img = f
im = Image.open(img)
width, height = im.size
pixels = list(im.convert('RGBA').getdata())
pixels = [pixels[i * width:(i + 1) * width] for i in range(height)]
# Rest of code unchanged
im1 = im.crop((left, top, right, bottom))
im1.save(img)
转换不会影响图像(它不会转换一个愚蠢的 RGBA 图像中的灰度图像,其所有 R=G=B,浪费空间),因为转换只是为了获得用于计算作物面积的像素阵列,并对未转换的原始图像进行裁剪。
我无法抗拒建议您不惜一切代价避免遍历像素的冲动。
您可以获取数据的 numpy 数组视图,而不是创建 python 列表(您必须自己重塑)。
import numpy as np
arr=np.asarray(im.convert('RGB'))
然后,检查一行i是否为白色
LineIisWhite=(arr[i]==255).all()
(arr[i]==255) 是一个布尔值数组,与你的线的形状相同,也就是说,这里是 W×3,那里是 True,那里是 255,其他地方是 False。
(arr[i]==255).all() 是一个布尔值,表示先前数组中的所有布尔值是否为真。所以如果线是白色的。
那仍然无法避免对行的迭代。但我们可以做得更好。
将 all 限制到最后 2 个轴(W 和 3),通过添加 axis=(1,2) 并应用于整个图像,我们得到一个 H 布尔值数组,如果每行中所有 W×3 布尔值都为真,则它们为真。
whitelines=(arr==255).all(axis=(1,2))
在我构建的示例图像中,结果是
array([ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True])
然后,不需要遍历这个布尔数组来计算开头或结尾的True的数量
crop_from_top = np.argmin(whitelines)
crop_from_bottom = np.argmin(whitelines[::-1])
所以,一共
import numpy as np
for f in pa_files:
img = f
im = Image.open(img)
width, height = im.size
arr = np.asarray(im.convert('RGB'))
whitelines=(arr==255).all(axis=(1,2))
crop_from_top = np.argmin(whitelines)
crop_from_bottom = np.argmin(whitelines[::-1])
# Setting the points for cropped image
left = 0
top = crop_from_top - 5
right = im.width
bottom = im.height - (crop_from_bottom- 5)
im1 = im.crop((left, top, right, bottom))
im1.save(img)
最后一点:由于索引必须近似颜色,甚至由于 JPEG 编码,白色像素可能不是纯白色。
因此,您可能希望将 arr==255 更改为 arr>=250 或类似的内容。
请注意,这里的 numpy 数组是只读的。我们只用它来计算要裁剪多少行。