Python 使用 opencv 的一些问题

2019-08-14 19:23:13 +08:00
 mostkia

需求说明: 我想使用 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 不久,卡住这个问题很久了,希望有人能够指点一下,谢谢。

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

如果你想用 JPG 压缩方式来加速传输,应该搜的是 『 javascript jpeg decoder 』。
secondwtq
2019-08-14 21:22:17 +08:00
@insaneguy 我没记得前端有不能直接用 base64 的 jpeg 这么一个事 ...
mostkia
2019-08-14 21:46:35 +08:00
@insaneguy jpg 压缩后并没有变成其他东西,它依旧是图片啊,只是质量下降了,可以转为 base64 的。只是目前的方法必须存入到文件中,然后再拿出来转成 base64,比较慢,有临时文件而已。base64 在前端是可以直接使用的,直接新建一个图片标签放到 src 里面就可以了。
minami
2019-08-14 21:58:48 +08:00
个人愚见,这种需求应该找一个 jpeg-turbo 的 python 包装库,不应该上 opencv
jdhao
2019-08-14 21:59:52 +08:00
可以实现,不过我只知道用 PIL 怎么弄,正好研究过。PIL 中的 Image.save 支持保存到 buffer io,避免了保存为临时硬盘文件再读取的尴尬,而且 save 时候可以指定压缩的质量,正好可以压缩图片。具体见 https://jdhao.github.io/2019/07/06/python_opencv_pil_image_to_bytes/#pil
secondwtq
2019-08-14 22:05:32 +08:00
@jdhao 文章里面不是有 OpenCV 么 ...
jdhao
2019-08-14 22:09:48 +08:00
@secondwtq 题主说要压缩,opencv imencode 不能压缩吧,我不确定。
secondwtq
2019-08-14 22:16:39 +08:00
jdhao
2019-08-14 22:21:30 +08:00
@secondwtq 我指的是我不知道能否可以像 PIL 一样指定压缩的程度,这个 imencode 我不熟悉
secondwtq
2019-08-14 22:23:47 +08:00
@jdhao "灵活度"和“能不能”差别还是很大的 ...
sadfQED2
2019-08-14 23:25:20 +08:00
你的压缩应该用 resize,然后把图片转 byte,然后 bese64,这样才能在内存中处理,imwrite 本来就是写文件
JerryCha
2019-08-15 10:00:30 +08:00
单纯的降低画质重编码应该找个 JPEG codec 库会比较好使,不应该上 OpenCV。
chunk
2019-08-15 23:57:20 +08:00
为什么要用 base64 而不直接用二进制数据?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/591928

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX