需求说明: 我想使用 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 不久,卡住这个问题很久了,希望有人能够指点一下,谢谢。
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 ``` |
2
RealMadrid 2019-08-14 19:36:02 +08:00
cv2.imencode 可以将 cv.mat 转化成可以在网络中传输的字节流
|
3
mostkia OP @RealMadrid 谢谢你提供的方案,我查了查资料,imencode()+imdecode()应该是需要配套使用的,前台 js 应该没有解码方法,如果没法解码,那基本没什么用处的。我主要是在后台取出图片,传输到前台渲染出图片来,在此基础上,图片尽量能够压缩一些,加快传输速度,图片有部分品质损失倒是可以接受的。
|
5
insaneguy 2019-08-14 21:07:08 +08:00
LZ 思路错了。JPG 压缩后是不能直接转 base64 的,就是转了你也没法直接用 base64 表示图像,还是需要 JPG 解压成图像字节流,然后才能用 base64 编码。 @RealMadrid 给出的方案就是把原始图像用 JPG 方式编码压缩,然后再传输。
如果你想用 JPG 压缩方式来加速传输,应该搜的是 『 javascript jpeg decoder 』。 |
7
mostkia OP @insaneguy jpg 压缩后并没有变成其他东西,它依旧是图片啊,只是质量下降了,可以转为 base64 的。只是目前的方法必须存入到文件中,然后再拿出来转成 base64,比较慢,有临时文件而已。base64 在前端是可以直接使用的,直接新建一个图片标签放到 src 里面就可以了。
|
8
minami 2019-08-14 21:58:48 +08:00
个人愚见,这种需求应该找一个 jpeg-turbo 的 python 包装库,不应该上 opencv
|
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
|
12
secondwtq 2019-08-14 22:16:39 +08:00
@jdhao OpenCV 的图像本身就是个 raw data 的矩阵没啥可 encode 的,那你觉得这个 encode 会是 encode 啥的 ...
https://github.com/opencv/opencv/blob/290da9384544d7a8709c8fe048eb70c95503d5c6/modules/imgcodecs/src/loadsave.cpp#L867 https://github.com/opencv/opencv/blob/290da9384544d7a8709c8fe048eb70c95503d5c6/modules/imgcodecs/include/opencv2/imgcodecs.hpp#L248 https://github.com/opencv/opencv/blob/master/modules/imgcodecs/test/test_jpeg.cpp |
13
jdhao 2019-08-14 22:21:30 +08:00 via Android
@secondwtq 我指的是我不知道能否可以像 PIL 一样指定压缩的程度,这个 imencode 我不熟悉
|
15
sadfQED2 2019-08-14 23:25:20 +08:00 via Android
你的压缩应该用 resize,然后把图片转 byte,然后 bese64,这样才能在内存中处理,imwrite 本来就是写文件
|
16
JerryCha 2019-08-15 10:00:30 +08:00
单纯的降低画质重编码应该找个 JPEG codec 库会比较好使,不应该上 OpenCV。
|
17
chunk 2019-08-15 23:57:20 +08:00 via Android
为什么要用 base64 而不直接用二进制数据?
|