首页   注册   登录
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 · 11 天前 · 992 次点击

    需求说明: 我想使用 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   11 天前
    可以了解下 `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   11 天前
    cv2.imencode 可以将 cv.mat 转化成可以在网络中传输的字节流
        3
    mostkia   11 天前
    @RealMadrid 谢谢你提供的方案,我查了查资料,imencode()+imdecode()应该是需要配套使用的,前台 js 应该没有解码方法,如果没法解码,那基本没什么用处的。我主要是在后台取出图片,传输到前台渲染出图片来,在此基础上,图片尽量能够压缩一些,加快传输速度,图片有部分品质损失倒是可以接受的。
        4
    secondwtq   11 天前 via iPad
    @mostkia 你确定?
        5
    insaneguy   11 天前
    LZ 思路错了。JPG 压缩后是不能直接转 base64 的,就是转了你也没法直接用 base64 表示图像,还是需要 JPG 解压成图像字节流,然后才能用 base64 编码。 @RealMadrid 给出的方案就是把原始图像用 JPG 方式编码压缩,然后再传输。

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