【问题标题】:PIL: scale image while maintaing highest possible qualityPIL:在保持最高质量的同时缩放图像
【发布时间】:2013-07-25 03:03:41
【问题描述】:

我正在使用 PIL 来缩放从 600 像素宽到 2400 像素宽到大约 200 像素宽的图像。我已经合并了Image.ANTIALIAS 并设置了quality=95 以尝试获得最高质量的图像。

但是,与原始图像相比,缩小后的图像质量仍然很差。

这是我正在使用的代码:

# Open the original image
fp = urllib.urlopen(image_path)
img = cStringIO.StringIO(fp.read())
im = Image.open(img)
im = im.convert('RGB')

# Resize the image
resized_image = ImageOps.fit(im, size, Image.ANTIALIAS) 

# Save the image
resized_image_object = cStringIO.StringIO()
resized_image.save(resized_image_object, image_type, quality=95)

按照这些比例缩放图像同时尽可能保持图像质量的最佳方法是什么?

我应该注意,我的主要目标是尽可能获得最高质量的图像。我并不真正关心这个过程在时间方面的效率。

【问题讨论】:

  • 我们可以看一些例子吗?即原始图像、使用脚本制作的缩小图像和使用 Photoshop 制作的缩小图像以进行比较?
  • 您通常最好遍历结果图像中的像素区域并查看它们映射回原始图像中的哪个区域。这对于旋转更重要,但也可能与完全任意缩放有关。
  • 您显示的代码可能是 PIL 可以做的最好的代码 - 您正在转换为 RGB 并使用 ANTIALIAS。我最近发现 ANTIALIAS 实际上是被认为相当不错的 Lanczos3 算法。我很想知道您发现结果中缺少什么?

标签: python python-imaging-library


【解决方案1】:

如果您无法使用 PIL 中的本机调整大小选项获得结果,您可以通过自己的调整大小函数运行它们来手动计算调整大小的像素值。调整图像大小有三种主要算法(据我所知):

  • 最近的邻居
  • 双线性插值
  • 双三次插值

最后一个将在最长的计算时间内产生最高质量的图像。为此,请想象较小图像的像素布局,然后将其放大以匹配较大图像,并考虑新像素位置将在旧像素位置上方的位置。然后对于每个新像素,取最近的 16 个像素(周围 4x4 半径)的平均值并将其用作新值。

小图像中每个像素的结果值将是大图像的平滑但清晰的调整大小版本。

更多阅读请看这里:Wikipedia - Bicubic interpolation

【讨论】:

  • PIL 内置了所有这些,顺便说一句。但是,Image.ANTIALIAS 是推荐用于缩小规模的算法。
  • +1 谢谢大家,是的,我已经在使用 Image.ANTIALIAS 算法了。
【解决方案2】:

尝试不同的方法。我不确定这是否会有所帮助,但不久前我做了类似的事情: https://stackoverflow.com/a/13211834/1339024

可能是 urlpath 上的原始图像一开始就没有那么好的质量。但如果你愿意,试试我的脚本。我做了它来缩小给定目录中的图像,但这部分可能有用:

parentDir = "Some\\Path"
width = 200
height = 200
cdpi = 75
cquality = 95
a = Image.open(parentDir+'\\'+imgfile) # Change this to your url type
iw,ih = a.size
if iw > width or ih > height:
    pcw = width/float(iw)
    pch = height/float(ih)
    if pcw <= pch:
        LPC = pcw
    else:
        LPC = pch
    if 'gif' in imgfile:
        a = a.convert("RGB")#,dither=Image.NONE)
        a = a.resize((int(iw*LPC),int(ih*LPC)),Image.ANTIALIAS)
        a = a.convert("P", dither=Image.NONE, palette=Image.ADAPTIVE)
        a.save(outputDir+"\\"+imgfile,dpi=(cdpi,cdpi), quality=cquality)
    else:
        a = a.resize((int(iw*LPC),int(ih*LPC)),Image.ANTIALIAS)
        a.save(outputDir+"\\"+imgfile,dpi=(cdpi,cdpi), quality=cquality)

【讨论】:

  • *对不起标签,这是不久前做的,完全忘记了这些首字母缩略词代表什么。我相信 pcw 和 pch 代表 PercentChange of dimension(虽然不是真正的百分比变化),而 LPC 是 LowestPercentChange(同上)。
  • @rollingstone 让我知道它是如何工作的。此外,如果您在执行此操作时遇到问题,请随时告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-27
  • 1970-01-01
  • 2010-09-19
相关资源
最近更新 更多