从JPG到b64编码再到cv2.imread()

6

我正在编写一个程序,需要从一台计算机传输图像。使用base64.b64encode(f.read(image))方法,但在接收脚本中尝试读取该图像时,不想将其保存到硬盘上(以减少进程时间)。我很难想象如何将图像读入OpenCV而又不将其保存到本地。

以下是发送图像的代码:

f = open(image.jpg)
sendthis = f.read()
f.close()
databeingsent = base64.b64encode(sendthis)
client.publish('/image',databeingsent,0) 
# this is an MQTT publish, details for SO shouldn't be relevant

同时,这是接收它的代码。(由于我正在使用MQTT进行传输,所以这是在on_message函数中。)

def on_message(client, userdata, msg): # msg.payload is incoming data
    img = base64.b64decode(msg.payload)
    source = cv2.imread(img)
    cv2.imshow("image", source)

消息解码后,出现了错误:“TypeError:您的输入类型不是numpy数组”。
我进行了一些搜索,但似乎找不到相关的解决方法 - 一些存在于使用b64从文本文件转换为numpy的解决方案,但没有真正涉及使用图像并立即将解码数据读入OpenCV,而不是将其保存到硬盘(使用“发送”脚本中用于读取文件的反向过程)。
我仍然对Python和OpenCV很陌生,因此如果有更好的编码方法来发送图像 - 任何解决问题的方法都可以。发送图像的方式无关紧要,只要我能在接收端读取它,而不必将其保存为.jpg文件。
谢谢!

2
使用imdecode代替imread - Miki
"buf不是一个numpy数组,也不是标量" 尝试在这里传递b64decode步骤,仍然出现此错误。因此,仍然需要一个numpy数组。 - godfreap
看看 这个 是否有帮助。然后你需要使用 imdecode,因为 imread 是从磁盘加载图像。 - Miki
我之前看过那个,但并没有帮助。他们正试图做一些非常不同的事情,而我又没有足够的经验来从中得出有意义的例子/翻译。 - godfreap
1
可能 np.array(list(img), dtype=np.uint8) 或者 np.fromstring(img, dtype=np.uint8) 可以解决问题。但是我不懂 Python。我的建议只是你需要使用 imdecode。如何正确获取参数类型取决于你 :D - Miki
显示剩余4条评论
2个回答

16

你可以使用以下代码从解码数据中获取一个numpy数组:

import numpy as np
...
img = base64.b64decode(msg.payload)
npimg = np.fromstring(img, dtype=np.uint8)

那么,您需要使用imdecode函数从内存缓冲区中读取图像。而imread函数则是用来从文件中加载图像的。

因此:

import numpy as np
...
def on_message(client, userdata, msg): # msg.payload is incoming data
    img = base64.b64decode(msg.payload); 
    npimg = np.fromstring(img, dtype=np.uint8); 
    source = cv2.imdecode(npimg, 1)

你可能想删除最后一行的cv2.imshow - 当我这样做时,它会锁定。但那不是程序中关键的部分 - 它只是我插入的一个中间步骤,以使原始问题中的代码更有意义。重要的是,在此之前的所有内容都解决了我遇到的问题,现在一切都很好!谢谢! - godfreap
好的,谢谢。您可能需要使用cv2.waitKey(1)来查看_imshowed_图像并避免阻塞。 - Miki
是的,我遇到了这个问题,它仍然卡住了。我的程序与此交互的部分基本上做着相同的事情,这就是我在问题评论中提到的“新问题”。我认为这只是一个数据类型问题,应该很容易解决。再次感谢! :D - godfreap
嗨@Miki和@godfreap,我想问一下...在上面的代码中:source = cv2.imdecode(npimg, 1)中,1是一个标志(flag)...这里1的含义是什么?如果我没有设置flag=1会有什么区别吗? - wahyu
1
@uyhaW 是的,它是一个标志。在这里阅读(https://docs.opencv.org/master/d8/d6a/group__imgcodecs__flags.html#ga61d9b0126a3e57d9277ac48327799c80) - Miki
为了解释 source = cv2.imdecode(npimg, 1) 中的 1 是做什么的,我想花费一分钟时间:它相当于 cv2.IMREAD_COLOR,其作用是:如果设置,则始终将图像转换为3通道BGR彩色图像。 - Rocco Fortuna

4

从OpenCV 文档中可以看到:

imread:从文件中加载图像。

imdecode:从内存缓冲区中读取图像。

这似乎是实现您想要的更好的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接