三种图片转字符方式效率的比较

场景

我想通过json传输图片, 那么必须把图片转为string格式.
一般都是img->byte->string->byte->img的流程

四种方式的实现与比较

base64将img变为bytes有两种方式:b64encodeencodestring(虽然名字中有string, 但是转出来人然是bytes)
bytes转string有两种方式:decode("gbk")decode("utf-8")
一共有四种组合, 黑盒测试他们的时间开销.

import base64
from  time import time
from pprint import pprint
img_input = open("input.jpeg","rb").read()

res = []
T = time()
x = base64.b64encode(img_input).decode("gbk")
y = base64.decodebytes(x.encode("gbk"))
res.append((time()-T,len(x), "b64encode_gbk"))

T = time()
x = base64.b64encode(img_input).decode("utf-8")
y = base64.decodebytes(x.encode("utf-8"))
res.append((time()-T,len(x), "b64encode_utf-8"))

T = time()
x = base64.encodestring(img_input).decode("gbk")
y = base64.decodestring(x.encode("gbk"))
res.append((time()-T,len(x), "encodestring_gbk"))

T = time()
x = base64.encodestring(img_input).decode("utf-8")
y = base64.decodestring(x.encode("utf-8"))
res.append((time()-T,len(x), "encodestring_utf-8"))
print("时间开销从小到大:")
pprint(sorted(res, key=lambda x:x[0]))

print("字符串长度开销从小到大:")
pprint(sorted(res, key=lambda x:x[1]))


时间开销从小到大:
[(2.5272369384765625e-05, 6568, 'b64encode_utf-8'),
 (4.887580871582031e-05, 6655, 'encodestring_utf-8'),
 (0.0002677440643310547, 6655, 'encodestring_gbk'),
 (0.0004775524139404297, 6568, 'b64encode_gbk')]
字符串长度开销从小到大:
[(0.0004775524139404297, 6568, 'b64encode_gbk'),
 (2.5272369384765625e-05, 6568, 'b64encode_utf-8'),
 (0.0002677440643310547, 6655, 'encodestring_gbk'),
 (4.887580871582031e-05, 6655, 'encodestring_utf-8')]

为什么用base64

为了把图片转换为string, 我尝试了如下方法:

  • open(“xxx.jpeg”).read() 得到jpeg格式的bytes, 但是没有找到怎么转为为array的形式
  • cv2.imread(“xxx.jpeg”,1)的道array, 用array.tobytes()转换维bytes, 再用decode(“utf-8”)编码为字符串, 但是报错说该bytes以某个byte开头,不能够进行转换, 用gbk也是如此
  • 所以现在只能是cv2.imread(“xxx.jpeg”,1)得到array, 用base64.b64encode()转为bytes, 再用decode(“utf-8”)转为字符串

测试代码如下:

import numpy as np
import cv2
from PIL import Image
import base64
# 得到array
array_3d = cv2.imread("input.jpeg",1)
print("得到三维array_3d", type(array_3d), array_3d.shape)
array_1d = array_3d.ravel() #转换维一维
print("得到一维array_1d", type(array_1d), array_1d.shape)

bytes_ = base64.b64encode(array_1d)
print("得到bytes",type(bytes_))

string = bytes_.decode("utf-8")
print("得到string", type(string))
# 此处进行json传输


bytes_recv = string.encode("utf-8")
print("还原bytes", type(bytes_recv))

bytes_decode_recv = base64.decodebytes(bytes_recv)
print("解码后的bytes", type(bytes_decode_recv))

array_1d_recv = np.frombuffer(bytes_decode_recv,dtype=np.uint8)
print("还原一维array", type(array_1d_recv), array_1d_recv.shape)

array_3d_recv = array_1d_recv.reshape(*array_3d.shape)
print("还原三维array", type(array_3d_recv), array_3d_recv.shape)

cv2.imshow("",array_3d_recv)
cv2.waitKey(0)

如果正常, 则显示原来的图片

再次更新

前面的方法虽然能够转为string, 但是效率很低, 再传输前应该先压缩.
对于jpeg的bytes, 可以先转化为bytes buffer, 然后再通过PIL.Image.open(tempbuffer)得到array
测试代码如下:

from PIL import Image
import base64
from io import BytesIO 
# 得到array
bytes_ = open("input.jpeg","rb").read()
print("得到bytes", type(bytes_))

string = base64.b64encode(bytes_).decode("utf-8")
print("得到string", type(string))

print("传输string")

bytes_recv = base64.decodebytes(string.encode("utf-8"))
print("解码为bytes",type(bytes_recv) )


tempBuff = BytesIO()
tempBuff.write(bytes_recv)
tempBuff.seek(0)
print("创建byte buffer", type(tempBuff))
img_recv = Image.open(tempBuff)
print("得到image", type(img_recv))

再次更新

如果一开始获取的就是array的话. 测试代码如下:

import cv2
import numpy as np
import io
import base64
img_array = cv2.imread("input.jpeg",1)
print(type(img_array))
img_jpeg = cv2.imencode(".jpeg", img_array)[1].tostring()
print(type(img_jpeg))
string = base64.b64encode(img_jpeg).decode("utf-8")
print(type(string), len(string))
img_jpeg = base64.decodebytes(string.encode("utf-8"))
print(type(img_jpeg))
img_array = cv2.imdecode(np.fromstring(img_jpeg, dtype=np.uint8),1)
print(type(img_array))
cv2.imshow("",img_array)
cv2.waitKey(0)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值