Python PIL在裁剪时创建空白图像

Python PIL在裁剪时创建空白图像,python,python-imaging-library,crop,Python,Python Imaging Library,Crop,我正在处理约50MB(约19000像素x25500像素)的图像文件,并将它们裁剪成大小为4705像素x8375像素的图像。我编写了一个for循环,循环遍历包含95个图像的文件夹。在大多数情况下,裁剪效果很好,但在随机图像上,当代码裁剪图像时,子图像显示为空白图像。发生这种情况时,12幅图像中的第一幅将显示为正常(正确剪裁),但其余11幅图像将显示为空白。当问题没有发生时,所有12幅图像都会被正确裁剪 我正在MBP10.14.5上运行Spyder 3.3.4上的代码。PIL是版本1.1.7和Pyt

我正在处理约50MB(约19000像素x25500像素)的图像文件,并将它们裁剪成大小为4705像素x8375像素的图像。我编写了一个for循环,循环遍历包含95个图像的文件夹。在大多数情况下,裁剪效果很好,但在随机图像上,当代码裁剪图像时,子图像显示为空白图像。发生这种情况时,12幅图像中的第一幅将显示为正常(正确剪裁),但其余11幅图像将显示为空白。当问题没有发生时,所有12幅图像都会被正确裁剪

我正在MBP10.14.5上运行Spyder 3.3.4上的代码。PIL是版本1.1.7和Python 3.6。我已经检查了我是否正确地在图像上循环。重新运行失败(裁剪不正确)的图像,当我在其“打开”位置而不是“for循环”的一部分上裁剪它们时,效果良好

stepCounter=4705
对于os.listdir中的文件夹(位置):
如果文件夹==“MyFolder”:
对于os.listdir(位置+文件夹)中的文件:
重置计数器=-8375
对于范围(12)内的i:
打印(“迭代”,i,“文件上”,文件)
如果i%4==0:
重置计数器+=8375
左=0
顶部=0+重置计数器
右=4705
底部=8375+重置计数器
fileLocation=位置+文件夹+“/”+文件
newLocation=location+文件夹+“/”+文件[:-4]+str(i+1)+“.jpg”
img=Image.open(文件位置)
img=img.裁剪((左、上、右、下))
img.save(新位置)
img.close()
其他:
左=左+步进计数器
顶部=顶部
右=右+步进计数器
底部=底部
fileLocation=位置+文件夹+“/”+文件
newLocation=location+文件夹+“/”+文件[:-4]+str(i+1)+“.jpg”
img=Image.open(文件位置)
img=img.裁剪((左、上、右、下))
img.save(新位置)
img.close()
其他:
打印(“跳过”,文件夹)

同样,我希望图像是较大图像的子图像,而不是空白图像。不确定这是内存问题还是其他与代码无关的问题。

通过查看程序很难判断- 如果每个图像都像您描述的那样,那么它就可以工作了——但是,您的代码 因为命名目标图像没有使用防错误的编程模式,因为它们没有充分利用某些语言功能。该代码现在可以工作了,但可能需要一些尝试和错误才能实现。所以,我打赌,在某个时间点,一个错误的 此脚本已运行,在生成 目标切片文件。这次运行确实覆盖了一些图像,这些图像现在是 一片的大小

实际上,如果调用的
crop
方法超出了PIL图像对象上的图像像素大小,则不会产生任何错误:而是以静默方式创建一个零(黑色)图像

您没有提到,但是如果您要检查正在进行切片的图像 现在失败的情况是,您的原稿可能已经裁剪成更小的尺寸

此外,由于没有检查要裁剪的图像,如果多次运行此代码,则已保存的作物将被处理,就像它们再次是大图像一样

也就是说,在这个脚本的第一次运行时,“image.jpg”将被保存并通过“image12.jpg”裁剪为“image1.jpg”-但是在第二次运行时,这些“imageN.jpg”中的每一个都将变成“imageNM.jpg”-其中“M”再次从“1”变为“12”。此外,第一次运行“image11.jpg”和“image12.jpg”的第11和第12个图像将被第二次运行的第一和第二个输出替换

因此,如果您仍然可以使用25500 x 19000像素的图像恢复原始文件夹,并且只有这些图像,则可以运行此代码的重构版本,这将确保不会重新处理已经制作的切片。对图像宽度进行一次检查可以避免这种情况,更明确的命名模式也可能更好

另外,作为一些编码建议:

  • 使用Python的“f字符串”来处理名称
  • 使用Python的
    pathlib.Path
    操作文件夹名称并访问图像文件(这是Python 3.5中的新版本,周围的示例很少)
  • 避免在代码中使用硬编码的数字,只需将其作为变量放在列表的开头即可
  • 在x和y上使用显式迭代,而不是线性计数器,然后使用一些容易出错的算法来达到要裁剪的限制
  • 最后,正如我上面提到的,注意不要多次重读相同的图像,脚本会变得更容易看,并且不容易出错
还有一个机会,你真的击中了一个错误,在PIL,由于大图像大小,并未能从第二次加载大图像-但这是相当不可能的。如果出现此问题,则宁愿使用MemoryError停止程序

导入路径库
从PIL导入图像
#不管你用什么代码,都要得到“location”变量
...
x_阶跃=8375
y_阶跃=4705
全宽=25500
对于pathlib.path(location.glob(“***.jpg”)中的图像_路径:
#例如,Path.glob方法会在子文件夹中自动迭代
#与表达式匹配的所有文件
如果“MyFolder”不在image\u path.parts中:
#如果“MyFolder”不在图像文件的相对路径中,则跳过处理
持续
#一次性加载原始图像:
img=Image.open(图像路径)
如果img.width<全宽:
如果“裁剪”不在image_path.name中:
#不要印刷战争