OpenCV如何从缓冲区读取JPEG图像

27

我有一个包含jpeg图像数据的unsigned char*缓冲区。 我想使用c++和opencv显示该图像。 如果我执行以下操作:

Mat img(Size(640, 480), CV_8UC3, data);
namedWindow("image", 1);
imShow("image", img);

我得到了一个杂乱无序的像素图像。

我想这是因为数据是jpeg格式(带有头文件)。因为这个可以正常工作:

Mat imgbuf(Size(640, 480), CV_8UC3, data);
Mat img = imdecode(imgbuf, CV_LOAD_IMAGE_COLOR);

但是我不能使用imdecode函数,因为它基于GTK 2的highgui.h,而在我的项目中我使用GTK 3。

那么,如何显示缓冲区数据?除了opencv中的imdecode之外,是否有其他方法解码jpeg图像,如果这是问题的原因。 我真的不想重新构建带有Qt的opencv...

还有其他建议吗?

(使用Linux)


2
你不能使用 libjpeg 进行解码并完成吗?有什么问题吗? - mmgp
@mmgp 我会尝试使用libjpeg,只是想着能否在不包含其他库的情况下完成同样的事情。 - Matekk
1
如果您没有安装libjpeg,那么opencv将无法加载JPEG图像,因此不会包括其他库。 - mmgp
2
哇,你正在做的真的不好。在你的 Mat imgbuf(...) 行中,你读入了 640x480x3 字段的数据。由于 JPEG 是压缩的,JPEG 将确实轻松地适应其中。因此剩余的点将填充从内存中随机获取的数据,这非常糟糕。之后,您加载 Mat,其中包括 JPEG 和一堆随机内存数据,并对其进行解码。相反,首先将无符号字符缓冲区放入大小与缓冲区完全相同的向量或 mat 中,然后将其馈送到 imdecode 中。 - TimZaman
我猜2022年的情况已经改变了,因为imdecode现在是“imgcodecs.hpp”的一部分,而不是highgui,所以现在这是最好的方法。我有一个std::string类型的数据(为什么不呢),所以我正在使用以下代码:cv::Mat data(1, (int)str.size(), CV_8UC1, (void*)str.c_str()); 然后跟着 cv::imdecode(data, 0); - Octo Poulos
2个回答

59

我在网上看到很多对这个问题的回答都说应该直接调用libjpeg并跳过OpenCV的imread()例程。

这是不必要的!你可以使用imdecode()来从内存中解码原始图像缓冲区。但是做到这一点的方法并不直观,并且没有足够的文档帮助第一次尝试此操作的人。

如果您有原始文件数据的指针/大小(例如,直接从.jpg、.png、.tif等文件中读取),则可以进行如下操作:

int    nSize = ...       // Size of buffer
uchar* pcBuffer = ...    // Raw buffer data


// Create a Size(1, nSize) Mat object of 8-bit, single-byte elements
Mat rawData( 1, nSize, CV_8UC1, (void*)pcBuffer );

Mat decodedImage  =  imdecode( rawData /*, flags */ );
if ( decodedImage.data == NULL )   
{
    // Error reading raw image data
}

就是这样了!

希望这能对未来的某个人有所帮助。


它确实帮助了某个人。请注意,您使用了“size”而不是“nsize”,并且您可以直接从构造函数初始化rawData。 - user1418330
1
这对我没有用。从网络流中读取图像,保存到文件可以工作,但调用imdecode会给我一个灰色的窗口,cv :: imshow(“Window”,decodedImage)。 - aCuria
@aCuria 这可能是因为您在 imshow() 后忘记加上 cv2.waitKey(0)。 - Amir Rasti
1
这是很久以前的事情了,但我可以显示其他图像(从文件加载),所以我不认为waitKey是问题所在。 - aCuria
不需要“(void*)”,并且在imdecode中设置所需的标志(cv::IMREAD_COLOR)即可解决问题。 - Hossein

3
我已经使用 libjpeg 中的标准过程解压了 JPEG 图像,该过程在 libjpeg API 文档 的“解压细节”中有描述。
在解压数据后,您可以使用它来构建 cv::Mat. 请注意,解压后的图像为 RGB 格式,而 openCV 使用 BGR 格式,因此需要使用格式为 CV_RGB2BGRcvtColor() 操作。

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