opencv 无法打开 yuv422 图像而 rawpixels.net 可以显示图像

如何解决opencv 无法打开 yuv422 图像而 rawpixels.net 可以显示图像

我正在尝试打开 yuv 格式的图像。我可以用rawpixels.net打开,设置如下后显示

width:1920
height:1080
predefined format: yuv420 (nv12)
pixel format yuv

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

#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打开文件

找到示例图像 here

使用 rawpixels.net 打开的 yuv 图像看起来像这样。

enter image description here

谢谢,

解决方法

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


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

那么,文件中的图像数据在哪里?在开始时?在末尾?解决此问题的一种方法是将文件视为纯粹的灰度图像,看看是否有大块的黑色为零字节或填充。由于没有已知的图像大小,我通常以字节为单位获取文件大小,然后转到 Wolfram Alpha 网站并输入 "factors of XXX" 其中 XXX 是文件大小,然后选择 2文件大小平方根附近的数字,所以我得到一个方形的图像。因此,对于您,我选择了 2720x3072 并将您的文件视为该大小的单个灰度图像。在终端中使用 ImageMagick

magick -depth 8 -size 2720x3072 gray:camera_preview_250_2020_10_07_11_11_02.yuv image.jpg

enter image description here

一目了然,数据在文件的开头,文件的结尾是零填充,即黑色。如果黑色在图像的开头,我会占用最后的 H x W x 1.5 字节。

此步骤的另一种替代方法是将文件大小(以字节为单位)除以图像宽度以获取行数并查看其外观。所以您的文件是 8355840 字节,即 8355840/1920 或 4,325 行。让我们试试:

magick -depth 8 -size 1920x4352 gray:camera_preview_250_2020_10_07_11_11_02.yuv image.jpg

enter image description here

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


好的,如果您的数据是 YUV 或 NV12,那么最好的工具是 ffmpeg。我们已经知道数据位于文件的开头,并且我们知道尺寸和格式。我们也知道图像后面有填充,所以我们只需要像这样取第一帧:

ffmpeg -s 1920x1080 -pix_fmt nv12 -i cam*yuv -frames:v 1 image.png

enter image description here


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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?