
需求说明: 我想使用 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 年 8 月 14 日 可以了解下 `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 年 8 月 14 日 cv2.imencode 可以将 cv.mat 转化成可以在网络中传输的字节流 |
3 mostkia OP @RealMadrid 谢谢你提供的方案,我查了查资料,imencode()+imdecode()应该是需要配套使用的,前台 js 应该没有解码方法,如果没法解,那基本没什么用处的。我主要是在后台取出图片,传输到前台渲染出图片来,在此基础上,图片尽量能够压缩一些,加快传输速度,图片有部分品质损失倒是可以接受的。 |
5 insaneguy 2019 年 8 月 14 日 LZ 思路错了。JPG 压缩后是不能直接转 base64 的,就是转了你也没法直接用 base64 表示图像,还是需要 JPG 解压成图像字节流,然后才能用 base64 编码。 @RealMadrid 给出的方案就是把原始图像用 JPG 方式编码压缩,然后再传输。 如果你想用 JPG 压缩方式来加速传输,应该搜的是 『 Javascript jpeg decoder 』。 |
7 mostkia OP @insaneguy jpg 压缩后并没有变成其他东西,它依旧是图片啊,只是质量下降了,可以转为 base64 的。只是目前的方法必须存入到文件中,然后再拿出来转成 base64,比较慢,有临时文件而已。base64 在前端是可以直接使用的,直接新建一个图片标签放到 src 里面就可以了。 |
8 minami 2019 年 8 月 14 日 个人愚见,这种需求应该找一个 jpeg-turbo 的 python 包装库,不应该上 opencv |
9 jdhao 2019 年 8 月 14 日 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 年 8 月 14 日 @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 |
15 sadfQED2 2019 年 8 月 14 日 via Android 你的压缩应该用 resize,然后把图片转 byte,然后 bese64,这样才能在内存中处理,imwrite 本来就是写文件 |
16 JerryCha 2019 年 8 月 15 日 单纯的降低画质重编码应该找个 JPEG codec 库会比较好使,不应该上 OpenCV。 |
17 chunk 2019 年 8 月 15 日 via Android 为什么要用 base64 而不直接用二进制数据? |