首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >opencv不能打开yuv422图像,而rawpixels.net可以显示图像

opencv不能打开yuv422图像,而rawpixels.net可以显示图像
EN

Stack Overflow用户
提问于 2021-01-15 07:04:42
回答 1查看 924关注 0票数 1

我正在尝试打开一个yuv格式的图像。我可以用rawpixels.net打开它,并在设置以下内容后显示它

代码语言:javascript
复制
width:1920
height:1080
predefined format: yuv420 (nv12)
pixel format yuv

但是,如果我用opencv打开下面的代码,我就无法打开。

代码语言:javascript
复制
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>

int main() {
    std::cout << "OpenCV version: " << CV_VERSION << std::endl;


    cv::Mat image = cv::imread("camera_capture_256_2020_10_07_11_11_02.yuv");
    if (image.empty() == true) {

        std::cout << "image empty"<< std::endl;

        return 0;
    }   
        
    cv::imshow("opencv_logo", image);
    cv::waitKey(0);    

    return 0;
}

程序打印为“图像为空”。

我很困惑为什么不能用opencv打开这个文件。

样本图像被发现这里

用rawpixels.net打开的yuv图像应该是这样的。

谢谢,

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-16 16:10:51

在处理raw图像(RGB、BGR、YUV、NV12和其他图像)时,首先要做的就是知道图像像素的尺寸--没有这些图像,你真的很迷茫--尽管你可以做一些技巧来寻找相关性,以找到行宽,因为每行基本上都与上面的行类似。

下一步是检查文件大小是否正确。因此,如果是RGB和8位1920x1080,那么您的文件必须大小为1920x1080x3像素,如果没有问题的话。您的图像是1920x1080,NV12是12位或每像素1.5字节,所以我希望您的文件是1920x1080*1.5字节。不是这样的,所以马上就有问题了。有一个标题,或多个帧,或尾随数据或其他一些问题。

那么,文件中的图像数据在哪里呢?刚开始的时候?在最后?解决这一问题的一种方法是将文件视为纯粹的灰度图像,并查看是否有大的黑色块,即零字节或填充。由于没有已知的图像大小,我通常以字节为单位获取文件大小,然后转到沃尔夫拉姆阿尔法网站并键入“XXX的因素”,其中XXX是文件大小,然后在文件大小的平方根附近选择2个数字,这样我就可以得到一个方形的图像。因此,对于您的文件,我选择了2720x3072,并将您的文件作为该大小的单一灰度图像处理。在终端中使用ImageMagick

代码语言:javascript
复制
magick -depth 8 -size 2720x3072 gray:camera_preview_250_2020_10_07_11_11_02.yuv image.jpg

我一眼就可以看到,数据在文件的开头,文件的末尾是零填充,即黑色。如果黑色是在图像的开头,我将获得最后的H x W x 1.5字节。

这一步的另一种选择是取文件大小(以字节为单位),并将其除以图像宽度,以获得许多行,并查看它的外观。所以您的文件是8355840字节,即8355840/1920或4325行。让我们试试看:

代码语言:javascript
复制
magick -depth 8 -size 1920x4352 gray:camera_preview_250_2020_10_07_11_11_02.yuv image.jpg

这是非常令人鼓舞的,因为我们可以看到Y (灰度)图像在文件的开头和一些低分辨率的UV通道后面,并且事实上没有两个单独的通道跟随可能意味着它们是交错的,交替的UV样本,而不是平面的U样本,然后是V样本。

好的,如果您的数据是YUV或NV12,最好的工具是ffmpeg。我们已经知道数据在文件的开头,我们知道大小和格式。我们也知道在图像之后有填充,所以我们只需要像下面这样的第一帧:

代码语言:javascript
复制
ffmpeg -s 1920x1080 -pix_fmt nv12 -i cam*yuv -frames:v 1 image.png

现在我们对维度和格式有了信心,我们需要OpenCV来阅读。普通的cv2.imread()无法读取,因为它只是原始数据,而且与JPEG、PNG或TIFF不同,头中没有图像的高度和宽度--它只是纯粹的传感器数据。

因此,您需要使用常规的C/C++ read()系统调用来获得第一个1920x1080x1.5字节。然后,您需要在接收到的缓冲区上调用cv2.cvtColor(),以将其转换为常规的BGR格式Mat

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65731787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档