【发布时间】:2019-05-29 09:51:20
【问题描述】:
我正在通过网络(来自 Python)发送图像,并希望在接收端(在 C++ 中)从它们创建 OpenCV Mats。
它们是这样创建的:
image = self.camera.capture_image() # np.array of dtype np.uint8
h, w, c = image.shape # 4 channels
image = np.transpose(image, (2, 0, 1)) # transpose because channels come first in OpenCV (?)
image = np.ascontiguousarray(image, dtype='>B') # big-endian bytes
bytess = image.tobytes(order='C')
在此之后,我应该有一个数组,其中 3 个维度被展平,以便为每个通道附加单独的行,然后附加通道以形成最终的字节缓冲区。我已验证我的理解是正确的,以下成立
bytess[channel*height*width + i*wwidth + j] == image[channel, i, j]
[我觉得上面的部分其实并不重要,因为如果不正确,我会得到一个错误显示的图像,但至少我会有一个图像,比我现在更进一步。]
现在我正在尝试这样做:
char* pixel_data = … // retrieve array of bytes from message
// assume height, width and channels are known
const int sizes[3] = {channels, width, height};
const size_t steps[3] = {(size_t)height * (size_t)width, (size_t)height};
cv::Mat image(3, sizes, CV_8UC1, pixel_data, steps);
因此,我创建了一个具有三个维度的矩阵,其中元素类型为byte。我不太确定我是否正确确定了steps,但我认为它与documentation 匹配。
但是运行它只会崩溃
error: (-5:Bad argument) Unknown array type in function 'cvarrToMat'
将 RGBA(或 OpenCV 的 BGRA)图像序列化为字节缓冲区并使用 C++ API 从中创建cv::Mat 的正确方法是什么?
【问题讨论】:
-
我稍后会考虑这个问题,但目前我做了一些相关的事情,可能会给你一个想法......stackoverflow.com/a/55313342/2836621
-
您确定您有足够的网络带宽来执行此操作吗?即使是 640x480 的 RGB 图像也接近 1MB,而 100Mb/s 的以太网最高可以提供 8MB/s,那么每秒 8 帧是否足够?还是您需要 JPEG 编码并获得 20 倍?
-
@MarkSetchell 它是通过本地主机发送的,所以这个问题现在并不重要。我完全有兴趣让反序列化工作。
-
您的发送和接收代码在哪里?
-
为什么所有的恶作剧,numpy 数组的内存布局和
cv::Mat是相同的,您只需要获取底层数据缓冲区并为其创建一个具有相同尺寸的cv::Mat标头和元素数据类型。最小的开销,这就是 Python OpenCV 绑定的工作方式。