工作杂记-YUV的dump和read

工作小记-YUV的dump和read

  • 工作杂记-YUV的dump和read
  • 利用dump生成图片 yuv2img
  • yuv2img代码

工作杂记-YUV的dump和read

工作中涉及到模型验证相关的工作,这里是三个模型的共同作用,在感知模型读取图片的时候,把输入替换成自己给定的输入,保证一致性,再来看输出。
知道了模型输入的宽高和步长之后,有如下的dump_yuv和read_yuv函数。其中bpu_addr和bpu_addr_uv是y分量和uv分量的地址。

bool ReadYUVImage(const std::string &img_path, int width, int height,uint64_t bpu_addr, uint64_t bpu_addr_uv) {std::ifstream input_img_file(img_path, std::ios::binary);input_img_file.seekg(0, std::ios::end);int len = input_img_file.tellg();input_img_file.seekg(0, std::ios::beg);std::vector<uint8_t> img_data(width * height * 3 / 2);if (len < width * height * 3 / 2) {HSLOG_E << "file length is not right " << len << " img_file:" << img_path;return false;} else {input_img_file.read(reinterpret_cast<char *>(img_data.data()),width * height * 3 / 2);memcpy(reinterpret_cast<void *>(bpu_addr), img_data.data(), width * height);memcpy(reinterpret_cast<void *>(bpu_addr_uv),img_data.data() + width * height, width * height / 2);}input_img_file.close();return true;
}void DumpYUVImage(const std::string &out_file, int width, int height,uint64_t bpu_addr, uint64_t bpu_addr_uv) {std::ofstream fout(out_file, std::ios::out | std::ios::binary);std::vector<uint8_t> src_input_image(width * height * 3 / 2);memcpy(src_input_image.data(), reinterpret_cast<void *>(bpu_addr),width * height);memcpy(src_input_image.data() + width * height,reinterpret_cast<void *>(bpu_addr_uv), width * height / 2);fout.write(reinterpret_cast<char *>(src_input_image.data()),width * height * 3 / 2);fout.close();
}

利用dump生成图片 yuv2img

这里需要了解yuv相关的排布知识。
YUV格式有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。

YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

planar的YUV格式分为YUV420P和YUV420SP,YUV420P包含I420和YV12。I420格式和YV12格式的不同处在U平面和V平面的位置不同。在I420格式中,U平面紧跟在Y平面之后,然后才是V平面(即:YUV);但YV12则是相反(即:YVU)。
YUV420SP, Y分量平面格式,UV打包格式, 即NV12。 NV12与NV21类似,U 和 V 交错排列,不同在于UV顺序。
I420: YYYYYYYY UU VV =>YUV420P
YV12: YYYYYYYY VV UU =>YUV420P
NV12: YYYYYYYY UVUV =>YUV420SP
NV21: YYYYYYYY VUVU =>YUV420SP
yuv排布

注意转化时要知道文件的uv排列先后顺序,实测u,v颠倒后的图片色差会有变化。
正确的结果 👇
在这里插入图片描述
错误的结果👇
在这里插入图片描述

核心代码,这里有一个opencv的坑,在merge时 会报错Invalid number of channels in input image: ‘VScn::contains(scn)’ ‘scn’,原因时Y U V的shape不一致,解决方案时把UV插值成和Y一样的,在merge,这样shape就成了(h,w,3)这种形式。再调用cv2.COLOR_YUV2BGR去做转化。

    # 分离UV通道为U和VU = UV[:, ::2]V = UV[:, 1::2]# 扩展U和V通道为与Y通道一致的大小U = cv2.resize(U, (width, height), interpolation=cv2.INTER_LINEAR)V = cv2.resize(V, (width, height), interpolation=cv2.INTER_LINEAR)# 合并Y、U、V通道数据YUV420p_image = cv2.merge((Y, U, V))# 转换为RGB格式image_rgb = cv2.cvtColor(YUV420p_image, cv2.COLOR_YUV2BGR)

yuv2img代码

如下是根据dump的yuv文件生成图片,其中三个函数,分别为灰度(only y 分量),420sp直接转RGB,420sp 提取 U、V分量后,再插值和Y分量组成YUV444,再转成RGB。

Y = np.frombuffer(buffer[:Y_size], dtype=np.uint8).reshape(height, width)
UV = np.frombuffer(buffer[Y_size:], dtype=np.uint8).reshape(height // 2, width)# 分离UV通道为U和V
U = UV[:, ::2] # 实际上是选择 UV 数组的所有行,但只选择每一行中的偶数列元素,即第0列、第2列、第4列等
V = UV[:, 1::2] # 扩展U和V通道为与Y通道一致的大小
U = cv2.resize(U, (width, height), interpolation=cv2.INTER_LINEAR)
V = cv2.resize(V, (width, height), interpolation=cv2.INTER_LINEAR)# 合并Y、U、V通道数据
YUV420p_image = cv2.merge((Y, U, V))
import cv2
import numpy as np
import re
import osdef convert_YUV420sp_RGB(yuv_file):# 从文件名中提取宽度和高度match = re.search(r'_w_(\d+)_h_(\d+)', yuv_file)if match:width = int(match.group(1))height = int(match.group(2))else:print("无法提取分辨率信息:", yuv_file)returnprint(width, height)with open(yuv_file, "rb") as f:buffer = f.read()image = np.frombuffer(buffer, np.uint8).reshape(height*3//2, width)print(image.size, image.shape)image_rgb = cv2.cvtColor(image, cv2.COLOR_YUV420SP2RGB)yuv_file = os.path.basename(yuv_file)output_file = yuv_file.replace(".yuv", ".jpg")output_file = os.path.join(output_folder_path, f"{output_file}.jpg")cv2.imwrite(output_file, image_rgb)# print(output_file)def convert_YUV420sp_YUV444_RGB(yuv_file):# 从文件名中提取宽度和高度match = re.search(r'_w_(\d+)_h_(\d+)', yuv_file)if match:width = int(match.group(1))height = int(match.group(2))else:print("无法提取分辨率信息:", yuv_file)return# 读取YUV420sp图像数据with open(yuv_file, "rb") as f:buffer = f.read()# 解析Y、UV通道数据Y_size = width * heightUV_size = width * height // 2Y = np.frombuffer(buffer[:Y_size], dtype=np.uint8).reshape(height, width)UV = np.frombuffer(buffer[Y_size:], dtype=np.uint8).reshape(height // 2, width)# 分离UV通道为U和VU = UV[:, ::2]V = UV[:, 1::2]# 扩展U和V通道为与Y通道一致的大小U = cv2.resize(U, (width, height), interpolation=cv2.INTER_LINEAR)V = cv2.resize(V, (width, height), interpolation=cv2.INTER_LINEAR)# 合并Y、U、V通道数据YUV420p_image = cv2.merge((Y, U, V))# 转换为RGB格式image_rgb = cv2.cvtColor(YUV420p_image, cv2.COLOR_YUV2BGR)yuv_file = os.path.basename(yuv_file)output_file = yuv_file.replace(".yuv", ".jpg")output_file = os.path.join(output_folder_path, f"{output_file}.jpg")cv2.imwrite(output_file, image_rgb)# print(output_file)def convert_YUV420sp_GRAY(yuv_file):file_name = os.path.splitext(yuv_file)[0]match = re.search(r'_w_(\d+)_h_(\d+)', yuv_file)if match:width = int(match.group(1))height = int(match.group(2))else:print("无法提取分辨率信息:", yuv_file)return# 打开YUV文件并读取数据with open(yuv_file, 'rb') as file:buffer = file.read()Y_size = width * heightY_data = buffer[:Y_size]# 将Y数据转换为NumPy数组Y = np.frombuffer(Y_data, dtype=np.uint8).reshape((height, width))gray_image = cv2.cvtColor(Y, cv2.COLOR_GRAY2BGR)yuv_file = os.path.basename(yuv_file)output_file = yuv_file.replace(".yuv", ".jpg")output_file = os.path.join(output_folder_path, f"{output_file}.jpg")cv2.imwrite(output_file, gray_image)return# 定义输入YUV文件夹路径
input_folder_path = "./dump_yuv"  # 替换为包含YUV文件的文件夹路径# 定义输出JPEG文件夹路径
output_folder_path = input_folder_path + "_output"  # 保存JPEG文件的文件夹路径
if not os.path.exists(output_folder_path):os.makedirs(output_folder_path)# 获取输入文件夹中的所有YUV文件
yuv_files = [file for file in os.listdir(input_folder_path) if file.endswith(".yuv")]for yuv_file in yuv_files:print(yuv_file)# convert_YUV420sp_YUV444_RGB(input_folder_path + "/" + yuv_file)# convert_YUV420sp_RGB(input_folder_path + "/" + yuv_file)convert_YUV420sp_GRAY(input_folder_path + "/" + yuv_file)
model_id:0 percepts_[0] rect num:1
model_id:0 rect:388.95 1034.04 520.791 1163.19 7.03816 0
model_id:0 percepts_[5] rect num:8
model_id:0 rect:2164.7 1034.81 2261.26 1110.25 8.7623 5
model_id:0 rect:2464.56 996.751 2519.25 1059.25 7.19807 5
model_id:0 rect:2654.99 593.22 2744.83 696.733 8.5591 5
model_id:0 rect:2914.5 570.069 3007.19 666.134 8.76954 5
model_id:0 rect:3044.18 553.215 3152.04 664.448 8.68193 5
model_id:0 rect:3185.64 543.125 3295.19 652.673 7.15572 5
model_id:0 rect:3750.75 609.548 3836 781.291 8.73659 5
model_id:0 rect:3761.16 792.687 3836 1073.72 9.44854 5
model_id:0 percepts_[11] rect num:3
model_id:0 rect:247.464 1250.77 334.153 1311.08 7.29449 11
model_id:0 rect:1664.7 1409.73 2243.79 1526.45 7.30121 11
model_id:0 rect:3057.62 1149.15 3528.76 1186.85 7.29843 11
model_id:0 percepts_[13] rect num:3
model_id:0 rect:1390.61 1212.43 1441.98 1423.03 8.79426 13
model_id:0 rect:1992.3 1189.52 2025.68 1335.91 7.29169 13
model_id:0 rect:2816.59 1182.99 2865.39 1378.19 7.29921 13

再额外附一段画框的代码

import cv2
import re# 读取图片
image_path = './dump_yuv_v3_output/model_50_frame_1694608049106_w_3840_h_2160.jpg.jpg'
image = cv2.imread(image_path)# 打开包含矩形框坐标的文件
with open('rect.txt', 'r') as file:lines = file.readlines()# 正则表达式模式,用于匹配包含model_id和percepts的行
model_pattern = re.compile(r'model_id:\d+ percepts_\[(\d+)\] rect num:(\d+)')# 正则表达式模式,用于匹配包含model_id和rect的行
rect_pattern = re.compile(r'model_id:\d+ rect:(\d+(?:\.\d+)?) (\d+(?:\.\d+)?) (\d+(?:\.\d+)?) (\d+(?:\.\d+)?)')# 初始化一个字典来存储percepts_值和颜色的映射
percepts_color_mapping = {"0": (0, 0, 255),   # 红色"5": (0, 255, 0),   # 绿色"11": (255, 0, 0),   # 蓝色"13": (0, 255, 255), # 黄色
}# 遍历文件中的每一行
for line in lines:# 尝试匹配包含矩形坐标的行model_match = model_pattern.match(line)if model_match:percept_index = model_match.group(1)num_rects = model_match.group(2)print(f"Percept Index: {percept_index}")print(f"Number of Rectangles: {num_rects}")# 匹配对应的框rect_match = rect_pattern.search(line)if rect_match:x1, y1, x2, y2 = map(float, rect_match.groups())# 获取颜色color = percepts_color_mapping.get(percept_index)  # 默认为红色# 绘制矩形框x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)print(x1, y1, x2, y2)cv2.rectangle(image, (x1, y1), (x2, y2), color, 2)font = cv2.FONT_HERSHEY_SIMPLEXcv2.putText(image, str(percept_index), (x1, y1 - 10), font, 0.5, color, 1, cv2.LINE_AA)# 保存包含绘制框的图像
output_image_path = 'output_image.png'
cv2.imwrite(output_image_path, image)# 保存包含绘制框的图像
output_image_path = 'output_image.png'
cv2.imwrite(output_image_path, image)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/102042.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VBA入门2——程序结构

VBA基础入门2 VBA 程序结构VBA 程序结构入门&#xff08;认识 VBA 程序骨架&#xff09;循环结构判断结构 VBA 变量的声明和赋值&#xff08;使程序动起来&#xff09;不同变量类型声明语句如何声明多个变量声明变量是必须的嘛&#xff1f;变量赋值 VBA 程序顺序结构&#xff0…

3.3 数据定义

思维导图&#xff1a; 前言&#xff1a; **核心概念**&#xff1a; - 关系数据库支持**三级模式结构**&#xff1a;模式、外模式、内模式。 - 这些模式中包括了如&#xff1a;模式、表、视图和索引等基本对象。 - SQL的数据定义功能主要包括了模式定义、表定义、视图和索引的定…

Axure常用技巧及问题

以下内容将持续更新 目录 一、技巧1、版本选择2、快捷键3、定制工具栏 二、问题1、无法在浏览器预览2、发布到本地的HTML无法查看 一、技巧 1、版本选择 2、快捷键 3、定制工具栏 上方菜单栏-右键-自定义工具栏 二、问题 1、无法在浏览器预览 需要更改Axure配置 点击发布-…

C#之常见图形文件格式及其特点

部分内容来源于Microsoft相关文档&#xff01; 日常生活中和软件开发中&#xff0c;经常会用到图形文件格式&#xff1a; BMP BMP 是 Windows 用来存储与设备无关的图像和与应用程序无关的图像的标准格式。 给定 BMP 文件的每像素位数&#xff08;1、4、8、15、24、32 或 64…

嵌入式Linux裸机开发(六)EPIT 定时器

系列文章目录 文章目录 系列文章目录前言介绍配置过程 前言 前面学的快崩溃了&#xff0c;这也太底层了&#xff0c;感觉学好至少得坚持一整年&#xff0c;我决定这节先把EPIT学了&#xff0c;下面把常见三种通信大概学一下&#xff0c;直接跳过其他的先学移植了&#xff0c;有…

网页游戏的开发框架

网页游戏开发通常使用不同的开发框架和技术栈&#xff0c;以创建各种类型的游戏&#xff0c;从简单的HTML5游戏到复杂的多人在线游戏&#xff08;MMO&#xff09;等。以下是一些常见的网页游戏开发框架和它们的特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&a…

python安装geopy出现错误

python&#xff1a; 安装geopy出现错误 错误信息&#xff1a; 解决办法&#xff1a;再试一次 居然成功了&#xff0c;就是说&#xff0c;也不知道为什么

生产级Stable Diffusion AI服务部署指南【BentoML】

在本文中&#xff0c;我们将完成 BentoML 和 Diffusers 库之间的集成过程。 通过使用 Stable Diffusion 2.0 作为案例研究&#xff0c;你可以了解如何构建和部署生产就绪的 Stable Diffusion 服务。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 Stable Diffusion 2.0 …

uniapp微信小程序自定义封装分段器。

uniapp微信小程序自定义封装分段器。 话不多说先上效果 这里我用的是cil框架 vue3 下面贴代码 组价代码&#xff1a; <template><view class"page"><viewv-for"(item, index) in navList":key"index"click"changeNav(ind…

docker之Harbor私有仓库

目录 一、什么是Harbor 二、Harbor的特性 三、Harbor的构成 1、六个组件 2、七个容器 四、私有镜像仓库的上传与下载 五、部署docker-compose服务 把项目中的镜像数据进行打包持久数据&#xff0c;如镜像&#xff0c;数据库等在宿主机的/data/目录下&#xff0c; 一、什么…

idea将jar包deploy到本地仓库

1、pom.xml文件引入配置&#xff0c;如下参考&#xff1a; <distributionManagement><snapshotRepository><id>maven-snapshots</id><url>http://nexus1.coralglobal.cn/repository/maven-snapshots/</url></snapshotRepository><…

Maven 构建配置文件

目录 构建配置文件的类型 配置文件激活 配置文件激活实例 1、配置文件激活 2、通过Maven设置激活配置文件 3、通过环境变量激活配置文件 4、通过操作系统激活配置文件 5、通过文件的存在或者缺失激活配置文件 构建配置文件是一系列的配置项的值&#xff0c;可以用来设置…

Talk | ACL‘23 杰出论文,MultiIntruct:通过多模态指令集微调提升VLM的零样本学习

本期为TechBeat人工智能社区第536期线上Talk&#xff01; 北京时间10月11日(周三)20:00&#xff0c;弗吉尼亚理工大学博士生—徐智阳、沈莹的Talk已准时在TechBeat人工智能社区开播&#xff01; 他们与大家分享的主题是: “通过多模态指令集微调提升VLM的零样本学习”&#xff…

做一个物联网的后台程序与数据库设计

数据库部分 先设计一个简单的数据库。表结构如下: sql语句如下: SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for realtimedata -- ---------------------------- DROP TABLE IF EXISTS `realtimedata`

Godot快速精通-从看懂英文文档开始-翻译插件

视频教程地址&#xff1a;https://www.bilibili.com/video/BV1t8411q7hw/ 大家好&#xff0c;我今天要和大家分享的是如何快速精通Godot&#xff0c;众所周知&#xff0c;一般一个开源项目都会有一个文档&#xff0c;对于有一定基础或者是理解能力强的同学&#xff0c;看文档比…

跨境电商独立站,无货源,轻松卖全球~

在互联网全球化的现在&#xff0c;跨境电商已经成为越来越多企业和个人的选择。但运营过程中总会遇到各种各样的问题&#xff0c;比如库存压力大、语言沟通困难、物流费用高且慢等等。特别是在当下印尼电商禁止令出台&#xff0c;很多在各大电商平台的卖家更是苦不堪言。 因为市…

机器学习基础之《回归与聚类算法(1)—线性回归》

一、线性回归的原理 1、线性回归应用场景 如何判定一个问题是回归问题的&#xff0c;目标值是连续型的数据的时候 房价预测 销售额度预测 贷款额度预测、利用线性回归以及系数分析因子 2、线性回归定义 线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(…

翻译docker官方文档(残缺版)

Build with docker(使用 Docker 技术构建应用程序或系统镜像) Overview (概述) 介绍&#xff08;instruction&#xff09; 层次结构&#xff08;Layers&#xff09; The order of Dockerfile instructions matters. A Docker build consists of a series of ordered build ins…

数据挖掘实战(3):如何对比特币走势进行预测?

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

深度学习基础知识 最近邻插值法、双线性插值法、双三次插值算法

深度学习基础知识 最近邻插值法、双线性插值法、双三次插值算法 1、最近邻插值法 1、最近邻插值法 *最邻近插值&#xff1a;将每个目标像素找到距离它最近的原图像素点&#xff0c;然后将该像素的值直接赋值给目标像素 优点&#xff1a;实现简单&#xff0c;计算速度快缺点&…