python-imaging-library - 尽管`resample = Image.BICUBIC`,为什么PIL.Image.rotate()会导致质量下降
问题描述
根据https://stackoverflow.com/a/17822099/1639359使用resample=PIL.Image.BICUBIC
应该通过轮换保持质量。这个问题是我对上述答案的评论的跟进,它对我不起作用。
我们有什么版本的 Python 和 PIL:
import sys
print(sys.version)
3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0]
import PIL
import PIL.Image
print(PIL.__version__)
print(PIL.Image.__version__)
6.2.1
6.2.1
打开我们的测试图像,并保存它。
注意质量的损失;保存的文件比原始文件小得多:
img = PIL.Image.open('test_image.jpg')
holdexif = img.info['exif']
img.save('testsave.jpg',"jpeg",exif=holdexif)
%ls -l 'test_image.jpg'
%ls -l 'testsave.jpg'
-rwxrwxrwx 1 dino dino 1926859 Dec 24 21:28 test_image.jpg*
-rwxrwxrwx 1 dino dino 452343 Dec 27 13:16 testsave.jpg*
Per Determining JPG quality in Python (PIL)
设置quality='keep'
可防止保存时质量下降:
img.save('testsave.jpg',"jpeg",exif=holdexif,quality='keep')
%ls -l 'test_image.jpg'
%ls -l 'testsave.jpg'
-rwxrwxrwx 1 dino dino 1926859 Dec 24 21:28 test_image.jpg*
-rwxrwxrwx 1 dino dino 1926911 Dec 27 13:16 testsave.jpg*
如果我们旋转图像,会发生两件事:
img.format
消失- 质量显着降低(即使我们使用
resample=PIL.Image.BICUBIC
)
print(img.format)
JPEG
rotated_img = img.rotate(-90,resample=PIL.Image.BICUBIC,expand=True)
print(img.format)
print(rotated_img.format)
JPEG
None
保存旋转的文件显示质量损失:
rotated_img.format="JPEG" # quality='keep' will raise exception if format != 'JPEG'
rotated_img.save('testsave.jpg',"jpeg",exif=holdexif,quality='keep')
%ls -l 'test_image.jpg'
%ls -l 'testsave.jpg'
-rwxrwxrwx 1 dino dino 1926859 Dec 24 21:28 test_image.jpg*
-rwxrwxrwx 1 dino dino 450997 Dec 27 13:16 testsave.jpg*
问题:
1. 如果有的话,我做错了什么?
2. 为什么img.format
旋转消失?还有什么正在消失?
3.顺便说一句,有没有另一种方法来检测质量损失(我只知道保存文件并看到它要小得多)。
在@MarkRansom 的评论之后,我想为我的问题添加一些颜色:虽然我已经编码多年,但我直到上周才开始玩图像。 毫无疑问,我对图像处理的了解充其量是最少的,对事物的工作方式存在重大差距和误解。
也就是说,从编码的角度来看,我希望对象上的方法几乎只会执行该方法所建议的操作,而不会产生副作用。例如,我希望 rotate() 只旋转图像,而不是同时清除元数据。即使,为了效率起见,PIL 包的默认行为是始终删除元数据,我希望有一个选项(全局或基于每个方法),例如preserve_metadata=True
关于“判断质量的唯一好方法”是“看图像本身”,我当然可以理解这是绝对的情况。然而,在相对的基础上,最值得注意的是,在比较处理前后的“相同”图像时,在我看来,可能有一些方法可以物理测量或至少估计处理前后的质量差异。(当然,我对图像的了解还不够,无法知道最好的方法是什么;这也是我提出问题的部分原因)。在我看来(至少从我的初学者的角度来看),人们经常想做任何想要做的处理,而质量损失很少或没有损失同时。感谢您的耐心和帮助填补我的知识空白,并提供答案。
解决方案
通常,任何图像旋转都会导致图像质量下降,这仅仅是因为输出需要对输入进行插值,而不是从输入到输出的 1:1 映射。对于 90 度的倍数的旋转,可以获得 1:1 映射并进行无损旋转。目前尚不清楚 PIL/Pillow 是否足够聪明地做到这一点,但它可能会。您的示例旋转了 -90 度,因此您可能会走运。
元数据正在丢失,因为rotate
生成了一个新图像,它不会修改现有图像。确定哪些元数据可能与新图像相关并不容易,因此最安全的做法是不复制任何元数据。正如您所发现的,可以手动复制您认为重要的任何内容。我认为没有自动复制任何内容的选项。
正如评论中所指出的,使用文件大小来判断图像质量是一个非常糟糕的指标。较小的尺寸暗示质量较差,但不一定如此;JPEG 压缩的全部前提是在正常观看中根本看不到某些图像质量下降。视觉比较是终极测试。如果您必须进行自动比较,有一些方法可以做到这一点,但我认为没有任何一种方法成为无可争议的最佳比较方法。
推荐阅读
- python - 我正在尝试替换此函数中的列表,而无需再次重写整个函数
- macos - 当我是 root 时,如何获取登录用户的用户名或主目录?
- sed - sed:如何在非空行上添加到行首
- python-2.7 - 如何读取文本文件然后将其转换为元组列表
- git - 如何在带有私有存储库的詹金斯中使用 go 模块?
- java - Spring-boot,Spring-data,Hibernate保存@ManyToOne实体后重复键值违反唯一约束“b_name_key”
- reactjs - 在 React 应用程序的 shell 脚本中设置环境变量
- if-statement - “if”如何与verilog中的寄存器一起使用?
- r - 在向量上使用 ifelse
- excel - 打开新的 Chrome 标签页