首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
V2EX  ›  Python

Python 使用 opencv 的一些问题

  •  
  •   mostkia · 5 天前 · 933 次点击

    需求说明: 我想使用 opencv 的压缩图片功能,并且压缩完成后转为 base64 的编码返回给前台

    我的目前的代码是这样的:

    import cv2
    import base64
    
    img = cv2.imread("d:/aaa/1.jpg") #获取图片
    cv2.imwrite("d:/aaa/2.jpg",img,[cv2.IMWRITE_JPEG_QUALITY,40]) #压缩图片
    b64 = base64.b64encode(???)  #我如何拿到上面这行已经压缩好的图片,而不是将其输出到文件?
    

    但 opencv 似乎压缩完成之后就输出到文件了(其他的图片处理库比如 PIL 似乎也是这样,没法压图作为最后输出的一个可选功能),没法将处理过的数据其留存在变量里面,只能输出,查阅了相关资料也没什么收获。

    这导致如果我一定要实现这个功能的话,现有的方法必须先将压过的图片存入到临时文件,然后再读取出来转为 base64,代码写的狼狈不说,io 方面的损耗也是大,而且产生临时文件,是不是有什么好更好的方法?

    刚学 python 不久,卡住这个问题很久了,希望有人能够指点一下,谢谢。

    17 回复  |  直到 2019-08-15 23:57:20 +08:00
        1
    RealMadrid   5 天前
    可以了解下 `cv2.imencode` 的用法,例如
    ```
    def get_encode_image(origin_img):
    if origin_img is None:
    return ''
    img_encoded = cv2.imencode('.jpg', origin_img)[1]
    data_encoded = np.array(img_encoded)
    str_encoded = data_encoded.tostring()
    return str_encoded
    ```
        2
    RealMadrid   5 天前
    cv2.imencode 可以将 cv.mat 转化成可以在网络中传输的字节流
        3
    mostkia   5 天前
    @RealMadrid 谢谢你提供的方案,我查了查资料,imencode()+imdecode()应该是需要配套使用的,前台 js 应该没有解码方法,如果没法解码,那基本没什么用处的。我主要是在后台取出图片,传输到前台渲染出图片来,在此基础上,图片尽量能够压缩一些,加快传输速度,图片有部分品质损失倒是可以接受的。
        4
    secondwtq   5 天前 via iPad
    @mostkia 你确定?
        5
    insaneguy   5 天前
    LZ 思路错了。JPG 压缩后是不能直接转 base64 的,就是转了你也没法直接用 base64 表示图像,还是需要 JPG 解压成图像字节流,然后才能用 base64 编码。 @RealMadrid 给出的方案就是把原始图像用 JPG 方式编码压缩,然后再传输。

    如果你想用 JPG 压缩方式来加速传输,应该搜的是 『 javascript jpeg decoder 』。
        6
    secondwtq   5 天前
    @insaneguy 我没记得前端有不能直接用 base64 的 jpeg 这么一个事 ...
        7
    mostkia   5 天前
    @insaneguy jpg 压缩后并没有变成其他东西,它依旧是图片啊,只是质量下降了,可以转为 base64 的。只是目前的方法必须存入到文件中,然后再拿出来转成 base64,比较慢,有临时文件而已。base64 在前端是可以直接使用的,直接新建一个图片标签放到 src 里面就可以了。
        8
    minami   5 天前
    个人愚见,这种需求应该找一个 jpeg-turbo 的 python 包装库,不应该上 opencv
        9
    jdhao   5 天前 via Android
    可以实现,不过我只知道用 PIL 怎么弄,正好研究过。PIL 中的 Image.save 支持保存到 buffer io,避免了保存为临时硬盘文件再读取的尴尬,而且 save 时候可以指定压缩的质量,正好可以压缩图片。具体见 https://jdhao.github.io/2019/07/06/python_opencv_pil_image_to_bytes/#pil
        10
    secondwtq   5 天前
    @jdhao 文章里面不是有 OpenCV 么 ...
        11
    jdhao   5 天前 via Android
    @secondwtq 题主说要压缩,opencv imencode 不能压缩吧,我不确定。
        13
    jdhao   5 天前 via Android
    @secondwtq 我指的是我不知道能否可以像 PIL 一样指定压缩的程度,这个 imencode 我不熟悉
        14
    secondwtq   5 天前
    @jdhao "灵活度"和“能不能”差别还是很大的 ...
        15
    sadfQED2   5 天前 via Android
    你的压缩应该用 resize,然后把图片转 byte,然后 bese64,这样才能在内存中处理,imwrite 本来就是写文件
        16
    JerryCha   4 天前
    单纯的降低画质重编码应该找个 JPEG codec 库会比较好使,不应该上 OpenCV。
        17
    chunk   4 天前 via Android
    为什么要用 base64 而不直接用二进制数据?
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2612 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 19ms · UTC 00:46 · PVG 08:46 · LAX 17:46 · JFK 20:46
    ♥ Do have faith in what you're doing.