yuv420并转为bgr

news/2025/2/19 13:15:14/

文章目录

    • 从视频通道获取yuv视频帧数据y和uv,读取合并成完整yuv并转为bgr。
    • 详细解释
    • 进一步封装
      • ImageConverter.h
      • ImageConverter.cpp
      • main.cpp

从视频通道获取yuv视频帧数据y和uv,读取合并成完整yuv并转为bgr。

#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>int main() {const std::string yFile = "./Y.yuv";//自己替换const std::string uvFile = "./UV.yuv";//自己替换const int width = 1920;//自己替换const int height = 1080;//自己替换// 计算帧大小const int frameSize = width * height * 3 / 2;  // YUV420 图像每帧占用的字节数// 打开 YUV420 图片文件std::ifstream yfile(yFile, std::ios::binary);if (!yfile) {std::cerr << "Failed to open Y file." << std::endl;return 1;}std::ifstream uvfile(uvFile, std::ios::binary);if (!uvfile) {std::cerr << "Failed to open UV file." << std::endl;return 1;}// 读取 YUV 数据std::vector<uint8_t> yData(frameSize);yfile.read(reinterpret_cast<char*>(yData.data()), frameSize);std::vector<uint8_t> uvData(frameSize);uvfile.read(reinterpret_cast<char*>(uvData.data()), frameSize);// 提取 Y、U、V 分量std::vector<uint8_t> Y(width * height);std::vector<uint8_t> U(width * height / 4);std::vector<uint8_t> V(width * height / 4);std::copy_n(yData.begin(), width * height, Y.begin());std::copy_n(uvData.begin(),width * height / 4,U.begin());std::copy_n(uvData.begin() + width * height / 4,width * height / 4,V.begin());cv::Mat yuvImage(height * 3 / 2, width, CV_8UC1);std::memcpy(yuvImage.data, Y.data(), width * height);std::memcpy(yuvImage.data + width * height, U.data(), width * height / 4);std::memcpy(yuvImage.data + width * height * 5 / 4, V.data(), width * height / 4);cv::Mat bgrImage;cv::cvtColor(yuvImage, bgrImage, cv::COLOR_YUV2BGR_NV12);// 显示图像cv::imshow("YUV420 Image", bgrImage);cv::waitKey(6000);cv::destroyAllWindows();return 0;
}

详细解释

当然,我会逐行解释你的代码:

#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>

这些是 C++ 头文件引入部分。<iostream> 用于标准输入和输出,<fstream> 用于文件操作,<opencv2/opencv.hpp> 是 OpenCV 库的头文件,允许你使用 OpenCV 功能。

int main() {

这是 main 函数的开始。

const std::string yFile = "./Y.yuv";
const std::string uvFile = "./UV.yuv";

这里定义了两个字符串变量 yFileuvFile,用于存储 Y 和 UV 分量的文件路径。

const int width = 1920;
const int height = 1080;

这里定义了图像的宽度和高度。

const int frameSize = width * height * 3 / 2;

这是计算每帧图像的大小,因为 YUV420 图像中,Y 分量占据一帧的大小,而 U 和 V 分量各占据一帧大小的四分之一。这是根据 YUV420 格式的存储方式计算的。

std::ifstream yfile(yFile, std::ios::binary);
std::ifstream uvfile(uvFile, std::ios::binary);

这里打开了 Y 和 UV 分量的文件,使用了 ifstream 流,打开方式是二进制方式打开。

if (!yfile) {std::cerr << "Failed to open Y file." << std::endl;return 1;
}

这个条件语句检查是否成功打开了 Y 分量的文件,如果失败,则输出错误信息并返回 1,表示程序出错。

std::vector<uint8_t> yData(frameSize);
std::vector<uint8_t> uvData(frameSize);

这里定义了两个 std::vector,分别用于存储 Y 和 UV 分量的数据。它们的大小是一个帧的大小。

yfile.read(reinterpret_cast<char*>(yData.data()), frameSize);
uvfile.read(reinterpret_cast<char*>(uvData.data()), frameSize);

这里使用 read 函数从文件中读取 Y 和 UV 数据,注意通过 reinterpret_cast 进行了类型转换,因为文件操作需要 char* 类型。

std::vector<uint8_t> Y(width * height);
std::vector<uint8_t> U(width * height / 4);
std::vector<uint8_t> V(width * height / 4);

这里定义了三个 std::vector,分别用于存储提取出的 Y、U 和 V 分量数据。

std::copy_n(yData.begin(), width * height, Y.begin());
std::copy_n(uvData.begin(), width * height / 4, U.begin());
std::copy_n(uvData.begin() + width * height / 4, width * height / 4, V.begin());

这三行代码分别从 yDatauvData 中复制数据到 YUVstd::vector 中,确保正确提取了 Y、U、V 分量。

cv::Mat yuvImage(height * 3 / 2, width, CV_8UC1);

这里定义了一个 cv::Mat 对象 yuvImage,它将用于存储整个 YUV 图像,大小是 (height * 3 / 2) 行和 width 列,像素类型为 CV_8UC1(8 位无符号字符)。

std::memcpy(yuvImage.data, Y.data(), width * height);
std::memcpy(yuvImage.data + width * height, U.data(), width * height / 4);
std::memcpy(yuvImage.data + width * height * 5 / 4, V.data(), width * height / 4);

这三行代码使用 memcpy 函数将 Y、U、V 分量的数据复制到 yuvImage 中,确保它们按正确的顺序合并在一起。

cv::Mat bgrImage;
cv::cvtColor(yuvImage, bgrImage, cv::COLOR_YUV2BGR_NV12);

这里定义了 bgrImage,用于存储 BGR 格式的图像。然后,使用 OpenCV 的 cvtColor 函数将 YUV 图像转换为 BGR 格式,cv::COLOR_YUV2BGR_NV12 表示从 NV12 YUV 格式转换到 BGR 格式。

cv::imshow("YUV420 Image", bgrImage);
cv::waitKey(6000);
cv::destroyAllWindows();

最后,这几行代码显示图像。imshow 用于显示图像窗口,waitKey 用于等待按键,destroyAllWindows 用于关闭所有窗口。

这就是你代码的逐行解释。它的主要功能是打开 YUV420 文件,提取 Y、U、V 分量,将它们合并成 YUV 图像,然后将其转换为 BGR 格式并在窗口中显示。如果你有任何问题或需要更多解释,请随时提问。

进一步封装

ImageConverter.h

// ImageConverter.h
#pragma once#include <opencv2/opencv.hpp>class ImageConverter {
public:ImageConverter(const std::string& yFile, const std::string& uvFile, int width, int height);~ImageConverter();cv::Mat convertToBGR();void displayBGRImage();private:std::string yFile_;std::string uvFile_;int width_;int height_;cv::Mat yuvImage_;cv::Mat bgrImage_;
};
#pragma once

ImageConverter.cpp

// ImageConverter.cpp
#include "ImageConverter.h"
#include <fstream>
#include <iostream>ImageConverter::ImageConverter(const std::string& yFile, const std::string& uvFile, int width, int height): yFile_(yFile), uvFile_(uvFile), width_(width), height_(height) {const int frameSize = width * height * 3 / 2;std::ifstream yfile(yFile_, std::ios::binary);std::ifstream uvfile(uvFile_, std::ios::binary);if (!yfile || !uvfile) {std::cerr << "Failed to open YUV files." << std::endl;return;}std::vector<uint8_t> yData(frameSize);yfile.read(reinterpret_cast<char*>(yData.data()), frameSize);std::vector<uint8_t> uvData(frameSize);uvfile.read(reinterpret_cast<char*>(uvData.data()), frameSize);std::vector<uint8_t> Y(width * height);std::vector<uint8_t> U(width * height / 4);std::vector<uint8_t> V(width * height / 4);std::copy_n(yData.begin(), width * height, Y.begin());std::copy_n(uvData.begin(), width * height / 4, U.begin());std::copy_n(uvData.begin() + width * height / 4, width * height / 4, V.begin());yuvImage_ = cv::Mat(height * 3 / 2, width, CV_8UC1);std::memcpy(yuvImage_.data, Y.data(), width * height);std::memcpy(yuvImage_.data + width * height, U.data(), width * height / 4);std::memcpy(yuvImage_.data + width * height * 5 / 4, V.data(), width * height / 4);bgrImage_ = cv::Mat(height, width, CV_8UC3);cv::cvtColor(yuvImage_, bgrImage_, cv::COLOR_YUV2BGR_NV12);
}ImageConverter::~ImageConverter() {// 可以在这里添加清理资源的代码
}cv::Mat ImageConverter::convertToBGR() {return bgrImage_.clone();
}void ImageConverter::displayBGRImage() {cv::imshow("BGR Image", bgrImage_);cv::waitKey(60000);cv::destroyAllWindows();
}

main.cpp

// main.cpp (用法示例)
#include "ImageConverter.h"
int main() {const std::string yFile = "./Y.yuv";const std::string uvFile = "./UV.yuv";const int width = 1920;const int height = 1080;ImageConverter converter(yFile, uvFile, width, height);cv::Mat bgrImage = converter.convertToBGR();// 设置要保存的文件路径std::string filePath = "./your_image.png"; // 替换为你的文件夹路径和文件名// 保存BGR图像bool success = cv::imwrite(filePath, bgrImage);if (success) {std::cout << "图像已成功保存到文件夹:" << filePath << std::endl;}else {std::cerr << "保存图像时出错." << std::endl;}converter.displayBGRImage();return 0;
}

http://www.ppmy.cn/news/1205800.html

相关文章

哪种小型洗衣机好用?迷你洗衣机品牌推荐

随着科技的快速发展&#xff0c;现在的人们越来越注重自己的卫生问题&#xff0c;不仅在吃上面会注重卫生问题&#xff0c;在用的上面也会更加严格要求&#xff0c;而衣服做为我们最贴身的东西&#xff0c;我们对它的要求也会更加高&#xff0c;所以最近这几年较火爆的无疑是内…

Go进阶之rpc和grpc

文章目录 Go环境安装1&#xff09;windows2&#xff09;linux go语言编码规范1.1 包名&#xff1a;package1.2 ⽂件名1.3 结构体命名1.4 接⼝命名1.5 变量命名1.6 常量命名2.1 包注释2.2 结构&#xff08;接⼝&#xff09;注释2.3 函数&#xff08;⽅法&#xff09;注释2.4 代码…

目标检测标注的时代已经过去了?

在快速发展的机器学习领域&#xff0c;有一个方面一直保持不变&#xff1a;繁琐和耗时的数据标注任务。无论是用于图像分类、目标检测还是语义分割&#xff0c;长期以来人工标记的数据集一直是监督学习的基础。 然而&#xff0c;由于一个创新性的工具 AutoDistill&#xff0c;这…

linux 3.13版本nvme驱动阅读记录四

这里记录下在nvme_probe函数调用misc_register函数的总结。 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) {//... create_cdev://利用miscdev结构体提供一些字符设备的操作(回调函数)&#xff0c;用户空间可以下发一些nvme的命令等scnprintf…

VueCli 自定义创建项目及配置

一、VueCli 自定义创建项目 1.安装脚手架 (已安装) npm i vue/cli -g2.创建项目 vue create hm-exp-mobile选项 Vue CLI v5.0.8 ? Please pick a preset:Default ([Vue 3] babel, eslint)Default ([Vue 2] babel, eslint) > Manually select features 选自定义手动…

贪心:推公式

耍杂技的牛&#xff1a; 我们先分析每头牛的危险值 他前面牛的w(重量值)和 - 自身的s(强壮值)&#xff0c;要使每头牛的危险值最小&#xff0c;这显然是与w 和 s同时相关&#xff0c;所以先想出一种做法按 每头牛的w s进行升序排序(题见多了可能就会有这种题感)。接下来进行数…

虚幻引擎:如何在工程里面添加插件

1.在自己的项目中安装插件 在content目录下创建一个Plugins的文件,将插件文件放进去即可 2.在软件上安装,这样所有创建的项目都会带有此插件 将插件放在自己软件的这个目录下就好了

【踩坑】Putty报错: Can’t agree a key change algorithm

原因可能是putty版本太老了&#xff0c;更新putty就好了 下载地址&#xff1a;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 根据需要选择自己想要下载的版本&#xff0c;我是下载的如下图所示的版本。 另外&#xff0c;了解了一下Putty是用来远程连接…