文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

怎么使用python对图片进行批量压缩

2023-07-02 16:21

关注

本篇内容主要讲解“怎么使用python对图片进行批量压缩”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用python对图片进行批量压缩”吧!

使用Python和Pillow模块压缩图片

Pillow是Python上一个功能非常强大的图形处理库,若本地还没安装,可以通过指令:pip install Pillow安装。使用Pillow进行压缩的策略大致总结为三个:1、优化flag,2、渐进式JPEG,3、JPEG动态质量。

我们先用Python写一个简单的保存图片的例子:

from PIL import Imagefrom io import StringIOimport dynamic_qualityim = Image.open("photo.jpg")print(im.format,im.size,im.mode)new_photo = im.copy()new_photo.thumbnail(im.size,resample=Image.ANTIALIAS)save_args = {'format':im.format}if im.format=='JPEG':    save_args['quality'].value=85new_photo.save("copy_photo.jpg",**save_args)

1、优化flag

开启optimize设置,这是以CPU耗时为代价节省额外的文件大小,由于本质没变,对图片质量没有丝毫影响。

...if im.format=='JPEG':    save_args['quality'].value=85    save_args['optimize']=True...

2、渐进式JPEG

当我们将一张图片保存为 JPEG 时,你可以从下面的选项中选择不同的类型:

渐进式的选项可以在 Pillow 中轻松的启用 (progressive=True)。渐进式文件的被打包时会有一个小幅的压缩。

...if im.format=='JPEG':    save_args['quality'].value=85    save_args['optimize']=True    save_args['progressive=True']=True...

3、JPEG动态质量

最广为人知的减小 JPEG 文件大小的方法就是设置 quality。很多应用保存 JPEG 时都会设置一个特定的质量数值。

质量其实是个很抽象的概念。实际上,一张 JPEG 图片的每个颜色通道都有不同的质量。质量等级从 0 到 100 在不同的颜色通道上都对应不同的量化表,同时也决定了有多少信息会丢失。

在信号域量化是 JPEG 编码中失去信息的第一个步骤。

我们可以动态地为每一张图片设置最优的质量等级,在质量和文件大小之间找到一个平衡点。我们有以下两种方法可以做到这点:

Bottom-up: 这些算法是在 8x8 像素块级别上处理图片来生成调优量化表的。它们会同时计算理论质量丢失量和和人眼视觉信息丢失量。

Top-down: 这些算法是将一整张图片和它原版进行对比,然后检测出丢失了多少信息。通过不断地用不同的质量参数生成候选图片,然后选择丢失量最小的那一张。

我们选择第二种方法:使用二分法在不同的质量等级下生成候选图片,然后使用 pyssim 计算它的结构相似矩阵 (SSIM) 来评估每张候选图片损失的质量,直到这个值达到非静态可配置的阈值为止。这个方法让我们可以有选择地降低文件大小(和文件质量),但是只适用于那些即使降低质量用户也察觉不到的图片。

下面是计算动态质量的代码dynamic_quality.py:

import PIL.Imagefrom math import logfrom SSIM_PIL import compare_ssimdef get_ssim_at_quality(photo, quality):    """Return the ssim for this JPEG image saved at the specified quality"""    ssim_photo = "tmp.jpg"    # optimize is omitted here as it doesn't affect    # quality but requires additional memory and cpu    photo.save(ssim_photo, format="JPEG", quality=quality, progressive=True)    ssim_score = compare_ssim(photo, PIL.Image.open(ssim_photo))    return ssim_scoredef _ssim_iteration_count(lo, hi):    """Return the depth of the binary search tree for this range"""    if lo >= hi:        return 0    else:        return int(log(hi - lo, 2)) + 1def jpeg_dynamic_quality(original_photo):    """Return an integer representing the quality that this JPEG image should be    saved at to attain the quality threshold specified for this photo class.    Args:        original_photo - a prepared PIL JPEG image (only JPEG is supported)    """    ssim_goal = 0.95    hi = 85    lo = 80    # working on a smaller size image doesn't give worse results but is faster    # changing this value requires updating the calculated thresholds    photo = original_photo.resize((400, 400))    # if not _should_use_dynamic_quality():    #     default_ssim = get_ssim_at_quality(photo, hi)    #     return hi, default_ssim    # 95 is the highest useful value for JPEG. Higher values cause different behavior    # Used to establish the image's intrinsic ssim without encoder artifacts    normalized_ssim = get_ssim_at_quality(photo, 95)    selected_quality = selected_ssim = None    # loop bisection. ssim function increases monotonically so this will converge    for i in range(_ssim_iteration_count(lo, hi)):        curr_quality = (lo + hi) // 2        curr_ssim = get_ssim_at_quality(photo, curr_quality)        ssim_ratio = curr_ssim / normalized_ssim        if ssim_ratio >= ssim_goal:            # continue to check whether a lower quality level also exceeds the goal            selected_quality = curr_quality            selected_ssim = curr_ssim            hi = curr_quality        else:            lo = curr_quality    if selected_quality:        return selected_quality, selected_ssim    else:        default_ssim = get_ssim_at_quality(photo, hi)        return hi, default_ssim

然后在下面的代码中引用计算动态质量的方法:

...if im.format=='JPEG':    save_args['quality'],value=dynamic_quality.jpeg_dynamic_quality(im)    save_args['optimize']=True    save_args['progressive']=True...

使用Python和Selenium模块操纵Squoosh批量压缩图片

Squoosh 是谷歌发布的一款开源的图片在线压缩服务(伪),虽然需要用浏览器打开,但其实是一个整合了许多命令行工具的前端界面,调用的是本地的计算资源,所以只要打开过Squoosh一次,之后都会秒开,并且离线使用。不过最大的缺点就是不可以批量处理,如果我们要处理大量的图片资源,一张张地进行压缩处理将会消耗大量的人力成本和时间成本,这明显是不能接受的。我们要解决的问题就是写一个脚本来模拟浏览器的操作,使我们的双手得到解放。

Python 调用 Selenium

这是 Squoosh 的主界面,Select an Image 其实是一个输入框,那我们直接用 Selenium 把本地图片的路径输入进去就行了:

怎么使用python对图片进行批量压缩

输入图片路径之后就会默认压缩成 75% 质量的 MozJPEG,我觉得无论是压缩比和质量都很不错,所以就没有改,等待页面加载完成之后就直接下载:

怎么使用python对图片进行批量压缩

我们可以认为出现 "..% smaller" 就算是压缩完成,这时候直接点击右边的下载按钮即可。

代码:

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.ui import Selectimport osimport redriver = webdriver.Chrome('C:/Users/admin/AppData/Local/Google/Chrome/Application/chromedriver.exe')# 列出目录下所有的图片,存在 images 这个列表中images = os.listdir('C:/Users/admin/Pictures/Saved Pictures')# 处理所有图片for i in range(len(images)):    # 构建图片路径    path = 'C:/Users/admin/Pictures/Saved Pictures/' + images[i]    # 尝试处理所有图片    try:        # 打开 Squoosh        driver.get('https://squoosh.app')        # 找到输入框        input_box = driver.find_element_by_xpath('.//input[@class="_2zg9i"]')        # 输入图片路径        input_box.send_keys(path)        #设置图片格式        select1 = Select(driver.find_elements_by_css_selector('select')[-1])        if re.match('.*.png',images[i]):            select1.select_by_value("png")        if re.match('.*.jpg',images[i]):            select1.select_by_value("mozjpeg")        # 等待出现 'smaller'字样,10秒不出现则视为处理失败        locator = (By.XPATH, './/span[@class="_1eNmr _1U8bE"][last()]')        WebDriverWait(driver, 25).until(EC.text_to_be_present_in_element(locator, 'smaller'))        # 找到下载按钮        button = driver.find_elements_by_xpath('.//a[@title="Download"]')[-1]        # 点击下载按钮        button.click()    # 输出处理失败的图片路径    except:        print('*'*30)        print('Error: '+ path +' failed!')        print('*'*30)        continue

到此,相信大家对“怎么使用python对图片进行批量压缩”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯