当前位置: 首页 > news >正文

昇腾 - AscendCL C++应用开发 图像文件的解码时硬件对图像的宽度和高度的处理方式

昇腾 - AscendCL C++应用开发 图像文件的解码时硬件对图像的宽度和高度的处理方式

flyfish

假如是这样的

输入图片格式(YUV分量比例)

jpeg(420)

输出图片格式

YUV420SP NV12 8bit

输出图片宽、高对齐要求

宽2对齐
高2对齐

输出图片宽Stride、高Stride、内存大小要求

宽Stride为宽64对齐后的值。
高Stride为高16对齐后的值。
内存大小(单位Byte)≥ 宽Stride * 高Stride * 3/2

支持的硬件

Atlas 推理系列产品(Ascend 310P处理器)
Atlas 200/500 A2推理产品
Atlas A2训练系列产品

举例子

将ImageData 转cv::Mat格式
JPEGD(JPEG Decoder)对JPG图像文件的解码时,硬件对图像的宽度和高度存在对齐的要求

cv::Mat ImageDataToMat(const ImageData &imgData)
{// 确保图像格式是 YUV420SPif (imgData.format != PIXEL_FORMAT_YUV_SEMIPLANAR_420){throw std::invalid_argument("Unsupported image format");}std::cout << imgData.width << std::endl;std::cout << imgData.height << std::endl;// 创建 YUV420SP 的 cv::Matcv::Mat yuv420spMat(imgData.height + imgData.height / 2, imgData.width, CV_8UC1, imgData.data.get());// 将 YUV420SP 转换为 BGRcv::Mat bgrMat;cv::cvtColor(yuv420spMat, bgrMat, cv::COLOR_YUV2BGR_NV12);return bgrMat;
}

使用

string imgPath = "../data/1.jpg";
ImageProc imageProcess;
ImageData frame = imageProcess.Read(imgPath);cv::Mat bgrMat = ImageDataToMat(frame);
cv::imwrite("../data/2.jpg", bgrMat);

分析代码

ImageData 结构体
struct ImageData {std::shared_ptr<uint8_t> data = nullptr;uint32_t size = 0;uint32_t width = 0;uint32_t height = 0;uint32_t alignWidth = 0;uint32_t alignHeight = 0;acldvppPixelFormat format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;ImageData() {}ImageData(std::shared_ptr<uint8_t> buf, uint32_t bufSize,uint32_t x, uint32_t y, acldvppPixelFormat fmt) : data(buf), size(bufSize),width(x), height(y), format(fmt) {}
};
ImageProc的读取图像文件

可以是jpg或者png,Read函数中调用了ReadBinFile函数

ImageData ImageProc::Read(const string& filePath, acldvppPixelFormat imgFormat)
{// read file to host void* hostDataBuf = nullptr;uint32_t hostDataSize = 0;ReadBinFile(filePath, hostDataBuf, hostDataSize);int splitPos = filePath.find_last_of('/');string fileName = filePath.substr(splitPos + 1);// get file typeint pos = fileName.find('.');string fileType = fileName.substr(pos + 1);if (fileType=="jpg" || fileType=="jpeg" || fileType=="JPG" || fileType=="JPEG") {return JpegD(hostDataBuf, hostDataSize, imgFormat);} else if (fileType=="png") {return PngD(hostDataBuf, hostDataSize, imgFormat);} else {LOG_PRINT("[ERROR] Read file type not supported.");ImageData dst;return dst;}
}bool ReadBinFile(const string& fileName, void*& data, uint32_t& size)
{struct stat sBuf;int fileStatus = stat(fileName.data(), &sBuf);CHECK_RET(fileStatus == 0, LOG_PRINT("[ERROR] Failed to get input file."); return false);CHECK_RET(S_ISREG(sBuf.st_mode) != 0, LOG_PRINT("[ERROR] %s is not a file, please enter a file.", fileName.c_str()); return false);std::ifstream binFile(fileName, std::ifstream::binary);CHECK_RET(binFile.is_open() == true, LOG_PRINT("[ERROR] Open file %s failed", fileName.c_str()); return false);binFile.seekg(0, binFile.end);uint32_t binFileBufferLen = binFile.tellg();CHECK_RET(binFileBufferLen != 0, LOG_PRINT("[ERROR] Binfile is empty, filename is %s", fileName.c_str()); return false);binFile.seekg(0, binFile.beg);uint8_t* binFileBufferData = new(std::nothrow) uint8_t[binFileBufferLen];CHECK_RET(binFileBufferData != nullptr, LOG_PRINT("[ERROR] Malloc binFileBufferData failed"); return false);binFile.read((char *)binFileBufferData, binFileBufferLen);binFile.close();data = binFileBufferData;size = binFileBufferLen;return true;
}

解释 YUV420SP 的 cv::Mat

变量 cv::Mat yuv420spMat(imgData.height + imgData.height / 2, imgData.width, CV_8UC1, imgData.data.get());

YUV420SP NV12 8bit 表示一种图像数据格式,其中:
图像数据使用YUV颜色空间。
色度抽样比是4:2:0(每4个亮度样本对应2个色度样本)。
数据以半平面的方式存储,Y分量单独存储,而UV交替存储在一起。
每个分量的数据用8位表示。

详细点说就是
YUV颜色空间

  • Y 代表亮度(Luminance),即图像的明暗信息。
  • UV 代表色度(Chrominance),分别存储蓝色差(Cb)和红色差(Cr)信息。U和V共同决定了图像的颜色。

4:2:0 表示色度抽样的比例。它表明色度(U和V)的分辨率是亮度(Y)的一半,也就是说,每4个Y样本(即亮度值)只存储2个U和2个V样本。这样可以减少存储空间,同时保持相对较好的图像质量。

  • 4 :代表每4个像素的亮度样本。
  • 2 :代表在水平方向上每2个像素共享一个色度样本。
  • 0 :代表在垂直方向上每2行像素共享一个色度样本。

SP (Semi-Planar) 表示Y、U、V数据的存储方式。在YUV420SP中,Y分量的数据存储在一块连续的内存区域中,而U和V分量的数据交替存储在另一块连续的内存区域中。即,首先是Y数据,然后紧接着是交替存储的UV数据(UVUVUV…)。

NV12 是YUV420SP格式的一种具体形式。它规定在存储时,Y分量紧跟着UV分量存储,其中U在V之前排列(即UVUVUV…的顺序)。因此,NV12格式的图像数据首先是一个单独的Y平面,后面跟着交错的UV平面。

8bit 表示每个像素的亮度(Y)和色度(U和V)分量用8位表示。具体来说,Y、U、V的每个分量都有256个可能的值(从0到255),分别表示不同的亮度或颜色信息。

图像数据的存储结构

在 NV12 格式下,图像的存储结构如下:
Y 平面:首先存储所有像素的亮度(Y)信息,占据了整个图像的高度和宽度的内存空间。
UV 平面:紧接在 Y 平面之后,存储交替的 U 和 V 色度信息。因为色度分辨率是亮度的四分之一(在4:2:0抽样中),所以 UV 平面高度是原始图像高度的一半。

计算方式

硬件对图像的宽度和高度存在对齐的要求,因此引入了宽Stride和高Stride两个概念。宽Stride用于表示对齐后的宽度,高Stride用于表示对齐后的高度。假设宽Stride按照宽度的64倍对齐,高Stride按照高度的16倍对齐。那么,内存大小(单位Byte)需要满足以下公式:内存大小 ≥ 宽Stride * 高Stride * 3/2。

例如,对于一个500 × 300(宽度 × 高度)的图像,对齐后的宽高分别为512 × 304。具体计算如下:

  • 500 / 64 = 7.8125,由于需要向上对齐到最近的64的倍数,所以结果为64 × 8 = 512。

  • 300 / 16 = 18.75,由于需要向上对齐到最近的16的倍数,所以结果为16 × 19 = 304。

同样,对于一个1920 × 1080(宽度 × 高度)的图像,对齐后的宽高分别为1920 × 1088。

  • 宽度对齐:1920 / 64 = 30,直接为64 × 30 = 1920,因为1920已经是64的倍数。

  • 高度对齐:1080 / 16 = 67.5,需要向上取整到16的倍数,所以结果为16 × 68 = 1088。

这样可视化结果会存在高8像素的绿边

原图
图片描述
保存后 (如果按照1920 * 1080 直接存储,不进行任何处理, 会有一个8像素的绿边)

图片描述

关于功能及约束说明的参考

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python开发中,SQLAlchemy 的同步操作和异步操作封装,以及常规CRUD的处理。
  • Java 3.1 - 计算机网络
  • dubbo:dubbo+zookeeper整合nginx实现网关(四)
  • oracle liunx 常用命令
  • OpenID Connect(OIDC)认证--keycloak与springboot项目的整合
  • SpringBoot的内置缓存以及整合第三方缓存
  • 终端文档安全管理系统是什么?一文给你详解!
  • Spring Boot 3.3 【六】一文读懂 Logback 日志框架
  • 白酒与家庭:团圆时刻的需备佳品
  • 网络攻击常见技术方法(14种)
  • Kotlin学习-01创建kotlin学习环境
  • 程序员如何平衡日常编码工作与提升式学习?
  • RabbitMq实现延迟队列功能
  • 【CSS】使用 CSS 自定义属性(变量)-- var()
  • 基于python的汽车数据分析与可视化---附源码99290
  • Elasticsearch 参考指南(升级前重新索引)
  • java多线程
  • vue 配置sass、scss全局变量
  • 讲清楚之javascript作用域
  • 免费小说阅读小程序
  • ionic异常记录
  • 第二十章:异步和文件I/O.(二十三)
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​​​​​​​开发面试“八股文”:助力还是阻力?
  • ​2021半年盘点,不想你错过的重磅新书
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​secrets --- 生成管理密码的安全随机数​
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • #{}和${}的区别?
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (2)nginx 安装、启停
  • (3)STL算法之搜索
  • (ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类
  • (ZT)薛涌:谈贫说富
  • (八)Flask之app.route装饰器函数的参数
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)计算机毕业设计高校学生选课系统
  • (七)Flink Watermark
  • (七)理解angular中的module和injector,即依赖注入
  • (十八)Flink CEP 详解
  • (四)JPA - JQPL 实现增删改查
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)SvelteKit教程:hello world
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .jks文件(JAVA KeyStore)
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET 的程序集加载上下文
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .net访问oracle数据库性能问题
  • .NET中分布式服务
  • //usr/lib/libgdal.so.20:对‘sqlite3_column_table_name’未定义的引用
  • /proc/stat文件详解(翻译)
  • :class的用法及应用
  • ??javascript里的变量问题