V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
wzw
V2EX  ›  问与答

图片尺寸 1200x900 缩小到 800x600 有办法更清晰吗?(图片查看工具 100%>75%是更清晰的)

  •  
  •   wzw · 2020-11-18 09:39:14 +08:00 · 3307 次点击
    这是一个创建于 1501 天前的主题,其中的信息可能已经有所发展或是发生改变。
    目前用图片查看器缩小是会看得更清晰,100% > 75%的时候是更清晰的。 但是用 pillow 的 resize 就惨不忍睹了。

    1200x900 缩小到 800x600 或者 600x450

    有什么办法, 用 python 实现吗?

    原图:
    第 1 条附言  ·  2020-11-18 11:40:00 +08:00
    原图地址:
    37 条回复    2020-11-19 07:19:06 +08:00
    jdhao
        1
    jdhao  
       2020-11-18 09:47:57 +08:00 via Android
    resize 的时候是有 filter 参数可调节的,查一下,换一个高精度的 filter,默认的 filter 不行的
    wzw
        2
    wzw  
    OP
       2020-11-18 09:53:37 +08:00
    @jdhao #1 https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.resize

    请问你说的哪个参数, 我试过网上说的一些
    wzw
        3
    wzw  
    OP
       2020-11-18 09:55:09 +08:00
    @jdhao #1 基本都是说 Image.ANTIALIAS, 但是无效
    jdhao
        4
    jdhao  
       2020-11-18 10:00:16 +08:00
    @wzw 用 PIL 的话,PIL.Image.LANCZOS,这个精度应该是最高的,速度最慢
    jdhao
        5
    jdhao  
       2020-11-18 10:00:43 +08:00
    @jdhao 或者 bicubic 也试一下
    songzhengqian
        6
    songzhengqian  
       2020-11-18 10:16:35 +08:00
    个人观点:从大尺寸变为小尺寸分辨率就会降低,相当于压缩了。
    wzw
        7
    wzw  
    OP
       2020-11-18 10:17:21 +08:00
    @jdhao #4 @jdhao #5 LANCZOS/bicubic 效果都还是很模糊

    请看结果
    wzw
        8
    wzw  
    OP
       2020-11-18 10:18:12 +08:00
    @songzhengqian #6 但是 图片查看器缩小是会看得更清晰,100% > 75%、50%的时候是更清晰的

    是不是需要提升 dpi
    jdhao
        9
    jdhao  
       2020-11-18 10:33:06 +08:00
    @wzw Let me see see. 等会给你结果。
    ipwx
        10
    ipwx  
       2020-11-18 10:39:13 +08:00
    要不要试试输出 pdf 。。。
    jifengg
        11
    jifengg  
       2020-11-18 10:48:34 +08:00
    倒是没有看出缩小的时候哪里更清晰了。
    不过发现 v 站的图床,png 图片缩放之后尺寸反而大了,原图 20K,贴出来的大图是 80K 。 @livid
    xiangyuecn
        12
    xiangyuecn  
       2020-11-18 10:52:59 +08:00
    无法正确表达 0.49 像素,四舍五入为 0,普通缩放的时候那些斜线最容易丢失😂

    也许有专业的缩放工具,专门缩放线条曲线,图片缩放的时候线条粗细保持不变😂
    wzw
        13
    wzw  
    OP
       2020-11-18 11:39:00 +08:00
    @jdhao #9 等你结果,谢谢

    @ipwx #10 一定要图, 要插入到 word 用

    @jifengg #11 你用看图软件打开, 然后 100%》 50%试试

    @xiangyuecn #12 目前就是想和看图软件一样缩放就行
    wzw
        14
    wzw  
    OP
       2020-11-18 11:40:37 +08:00
    @jifengg #11 我也觉得奇怪, 应该这样看才是对的, 才是原图:

    https :// i.v2ex.co / CS69YwBh.png

    zhoushiya
        15
    zhoushiya  
       2020-11-18 11:54:51 +08:00
    wzw
        16
    wzw  
    OP
       2020-11-18 11:56:59 +08:00
    @zhoushiya #15 请问你是如何做到的, 谢谢!
    zhoushiya
        17
    zhoushiya  
       2020-11-18 11:59:33 +08:00
    @wzw #16 做图软件 firework 缩放的。。。。。。它也可以设置批处理脚本,你如果有大量图可以用批处理
    wzw
        18
    wzw  
    OP
       2020-11-18 12:03:19 +08:00
    @zhoushiya #17 😂, 我也知道 firework 可以实现, 想要的效果就是这样的。

    可是我需要用 python 或者其他编程语言来处理,firework 不方便了。。。
    also24
        19
    also24  
       2020-11-18 12:10:24 +08:00   ❤️ 1
    非整数倍的缩放,我一般习惯先放大再缩小,这是先将图片拉伸到 2400*1800,再缩小到 800*600 的效果。

    https://i.loli.net/2020/11/18/D2hibEvwmM1VLUN.png
    jdhao
        20
    jdhao  
       2020-11-18 12:10:37 +08:00   ❤️ 1
    @wzw 我试了 PIL 的所有 resample filter,似乎都不行,出来的都是模糊的,另外 Image.ANTIALIAS == Image.LANCZOS 。

    不过 opencv 的 resize 效果还行,下面是可运行的代码:

    import cv2

    def main():
    im = cv2.imread('big_image.png')
    im_resize = cv2.resize(im, (800, 600), interpolation=cv2.INTER_LANCZOS4)
    write_param = [cv2.IMWRITE_PNG_COMPRESSION, 5]
    cv2.imwrite('big-resized.png', im_resize, write_param)


    if __name__ == "__main__":
    main()


    上面的 interpolation 类似 PIL 中的 resample filter,除了 cv2.INTER_LANCZOS4,还可以试试 cv2.INTER_AREA,这俩出来的效果比较接近。还有一点值得注意的是,你给的原图只有 20kb 左右,opencv 出来的图片文件大小变大了不少,应该是压缩算法导致的,上面 wirte_param 那行可以调整压缩比例,最高 9,但是压缩下来的图片还是比原图大了不少。
    ipwx
        21
    ipwx  
       2020-11-18 13:25:03 +08:00
    @wzw 其实我指的是先 => pdf,然后用别的软件 => png 。哈哈哈
    ipwx
        22
    ipwx  
       2020-11-18 13:26:18 +08:00
    pdf2png 你可以试试 imagemagick 。我反正日常用一个脚本:

    #!/bin/bash
    DPI="${DPI:-192}"
    FROM="$1"
    DST="$2"
    BGARGS="$3"
    if [ "${FROM}" = "" ]; then
    echo "pdf2png from-file [to-file]"
    fi
    if [ "${DST}" = "-white" ]; then
    DST=""
    BGARGS="white"
    fi
    if [ "${DST}" = "" ]; then
    DST="${FROM/.pdf/.png}"
    fi
    if [ "${BGARGS}" != "" ]; then
    BGARGS="-background ${BGARGS} -alpha background -alpha remove"
    fi
    convert -density "${DPI}" -strip -trim "${FROM}" -quality 100 ${BGARGS} "${DST}"
    futou
        23
    futou  
       2020-11-18 13:53:52 +08:00
    就几张图的话:图片查看器缩小 ->截图另存为 😂 笨办法也许更快
    wzw
        24
    wzw  
    OP
       2020-11-18 13:54:31 +08:00
    @ipwx #21 还要绕一次 pdf 呀,,,我目前方案首选图片直接处理吧,
    wzw
        25
    wzw  
    OP
       2020-11-18 13:55:18 +08:00
    @futou #23 很多很多, 必须集成到系统里面的
    futou
        26
    futou  
       2020-11-18 14:31:30 +08:00
    @wzw 你发的原图是调色板图像,也许这是你处理结果不好的原因?我试了试 matlab 的 imresize,不放大看的话,默认参数缩放结果就非常清晰,你也可以试试 scipy 里的 imresize,结果也不差。
    ipwx
        27
    ipwx  
       2020-11-18 14:32:49 +08:00
    @wzw 如果你是 matplotlib 产生的图,你指定 plt.figure(figsize=) 就可以控制输出图像大小了。最好把两边空白也裁了,我记得是 plt.tight_layout() 还是啥。。。
    wzw
        28
    wzw  
    OP
       2020-11-18 15:22:03 +08:00
    @ipwx #27 matplotlib 以后还有一些二次处理的动作, 所以这条不适用, 一定要多次调整大小了
    wzw
        29
    wzw  
    OP
       2020-11-18 15:24:50 +08:00
    @futou #26 调色板图像? 我目前用的是 matplotlib fig.savefig 直接保存的
    ipwx
        30
    ipwx  
       2020-11-18 15:41:30 +08:00
    @wzw 把 pdf 输出到临时目录,然后用其他工具转换成 png 。
    JCZ2MkKb5S8ZX9pq
        31
    JCZ2MkKb5S8ZX9pq  
       2020-11-18 15:46:24 +08:00   ❤️ 1
    其实上面说的几种缩图算法应该是对的,缩出来的线条断点就是取样的问题。

    img.thumbnail((long_edge_limit, long_edge_limit), Image.ANTIALIAS)

    直接拿这句试了试,导出为 png 。
    thumbnail 是限制长边,自动缩。长边 800 。



    提供几个思路哦
    原图如果不是 rgb,而是类似 gif 的 256 色 pattern,会导致颜色不足从而掉色,要先转模式。
    缩图之后直接 show 一下看看。
    然后再存盘,看看会不会是导出格式的问题。
    jdhao
        32
    jdhao  
       2020-11-18 15:51:37 +08:00
    @JCZ2MkKb5S8ZX9pq 有道理,楼主原图是 RGBA 格式的 PNG 图片,并且是 palette 图像,我试了一下 PIL 读取图像,然后再转 RGBA 格式 ( palette 图像转 RGBA ),然后再 resize 和 save,图像质量高了很多。
    JCZ2MkKb5S8ZX9pq
        33
    JCZ2MkKb5S8ZX9pq  
       2020-11-18 16:03:05 +08:00
    @jdhao

    一种可能是导入后格式被修改过了,还有一种可能是代码出了问题。因为他出错的图明显是 nearest 采样的,刚看了下文档,版本问题好像会影响默认值。

    If omitted, it defaults to PIL.Image.ANTIALIAS. (was PIL.Image.NEAREST prior to version 2.5.0)

    但是考虑到 lz 试了好几种,所以感觉可能是参数没起效果(但回退到了 nearest )。
    也就是说如果 lz 的 PIL 是 2.5 以下的,可能是参数没加对。如果是新版本,那可能是图本身的问题。可以考虑在格式转换前后都打印一下颜色模式,或者 png 输出的话,强制加一步模式转换试试看。

    img = img.convert('RGBA')
    JCZ2MkKb5S8ZX9pq
        34
    JCZ2MkKb5S8ZX9pq  
       2020-11-18 16:06:46 +08:00   ❤️ 1
    上面是 thumbnail 的,resize 的写得更清楚。

    If omitted, or if the image has mode “1” or “P”, it is set PIL.Image.NEAREST.

    那就是去查图像 color mode 了。

    [Image Module — Pillow (PIL Fork) 2.6.1 documentation]( https://pillow.readthedocs.io/en/3.0.0/reference/Image.html)
    jdhao
        35
    jdhao  
       2020-11-18 16:13:55 +08:00 via Android
    @JCZ2MkKb5S8ZX9pq 嗯,那就解释了为啥设置其他 filter 没效果了,因为是楼主的原图片是 mode 是 P,所以强制使用 PIL.Image.NEAREST 来采样的。

    你看的仔细,我看到这个时候没意识到是因为图像模式问题,赞👍
    JCZ2MkKb5S8ZX9pq
        36
    JCZ2MkKb5S8ZX9pq  
       2020-11-18 18:16:32 +08:00
    @jdhao 美工出身,对这个比较敏感。
    wzw
        37
    wzw  
    OP
       2020-11-19 07:19:06 +08:00
    @also24 #19 你是直接用 pillow 吗?
    @JCZ2MkKb5S8ZX9pq #33 厉害,不愧是美工出生,我今天试试 img = img.convert('RGBA')
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   950 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 20:11 · PVG 04:11 · LAX 12:11 · JFK 15:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.