V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
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
mostkia
V2EX  ›  Python

Python 使用 opencv 的一些问题

  •  
  •   mostkia · 2019-08-14 19:23:13 +08:00 · 3190 次点击
    这是一个创建于 1932 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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