c++ - 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打开文件。
示例图像可在此处找到。
用 rawpixels.net 打开的 yuv 图像看起来像这样。
谢谢,
解决方案
处理原始(RGB、BGR、YUV、NV12 和其他)图像时要做的第一件事是了解图像的像素尺寸——没有这些你真的很迷茫——尽管你可以做一些技巧来寻找相关性以找到行宽,因为每一行通常与上面的行基本相似。
接下来是检查文件大小是否正确。因此,如果它是 RGB 和 8 位 1920x1080,则您的文件大小必须为 1920x1080x3 像素 - 如果不是,则存在问题。您的图像为 1920x1080 和 NV12,即每像素 12 位或 1.5 字节,所以我希望您的文件为 1920x1080*1.5 字节。不是这样的,所以马上就有问题了。有一个标题,或多个帧或尾随数据或其他一些问题。
那么,文件中的图像数据在哪里呢?在开始时?在最后?解决此问题的一种方法是将文件视为纯粹的灰度图像,并查看是否有大块零字节或填充的黑色块。由于没有已知的图像大小,我通常以字节为单位获取文件大小并访问Wolfram Alpha网站并输入“XXX 的因子”,其中 XXX 是文件大小,然后选择文件大小平方根附近的 2 个数字所以我得到了一个方形的图像。因此,对于您的,我选择了 2720x3072 并将您的文件视为该尺寸的单个灰度图像。在终端中使用ImageMagick :
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 或 4,325 行。让我们试试:
magick -depth 8 -size 1920x4352 gray:camera_preview_250_2020_10_07_11_11_02.yuv image.jpg
这是非常令人鼓舞的,因为我们可以看到Y
文件开头的(灰度)图像和一些较低分辨率的UV
通道,并且后面没有 2 个单独的通道这一事实可能意味着它们是隔行扫描、交替U
和V
采样而不是平面U
样品后跟V
样品。
好的,如果您的数据是 YUV 或 NV12,那么最好的工具就是ffmpeg
. 我们已经知道数据位于文件的开头,并且我们知道尺寸和格式。我们也知道图像后面有填充,所以我们只需要像这样取第一帧:
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
。
推荐阅读
- sublimetext3 - 使 Sublime Text 书签列不敏感
- c# - 用于移动和碰撞对象的性能更好的四叉树
- python - 转变
到'0'和'1' python的字符串 - java - 如果页面上存在该元素,如何出现在控制台中
- java - 如何在后台以特定间隔重复执行java文件?
- c# - 如何在我的代码中实现“if (TargetToFind != null)”以修复“Missing Reference Exception: error message
- angular - 如何在 PDFMake 中使用 Cordova 相机图片?
- api - 谷歌物联网谷歌云平台控制台中的“创建注册表”按钮在哪里?
- xslt-2.0 - 如何使用 xsl 为带有嵌套标签的父标签
- git - “git reset --hard”命令不会删除不必要的提交