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

news2024/11/15 8:46:07

昇腾 - 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)
{
    // 确保图像格式是 YUV420SP
    if (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::Mat
    cv::Mat yuv420spMat(imgData.height + imgData.height / 2, imgData.width, CV_8UC1, imgData.data.get());

    // 将 YUV420SP 转换为 BGR
    cv::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 type
    int 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像素的绿边)

图片描述

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

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

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

相关文章

CMake构建学习笔记2-zlib库的构建

文章目录 1. 概述2. 详论2.1 设置构建目录2.2 配置构建2.3 构建项目2.4 安装项目2.5 清理构建目录 3. 总结 1. 概述 Zlib是一个数据压缩库&#xff0c;它提供了在内存中对数据进行压缩和解压缩的功能。这个库非常泛用&#xff0c;除了直接使用这个库之外&#xff0c;很多依赖库…

学历不高能进大厂么?

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

《终身学习——10个你必须掌握的未来生存法则》读书笔记

无论你遵守与否&#xff0c;大自然的法则是无法改变的&#xff0c;你若无视“重力法则”&#xff0c;从屋顶跳下&#xff0c;那给你善后的就不是“重力警察”了。同理&#xff0c;如果你不遵循成长法则&#xff0c;也不会有“成长警察”找你麻烦&#xff0c;你只会发现自己的成…

结合 curl 与住宅代理实现高效数据抓取

引言 什么是 curl&#xff1f;有哪些功能&#xff1f; 基本 curl 命令有哪些&#xff1f; 为什么要使用 curl 处理 HTTP 请求&#xff1f; 如何使用 curl 和住宅代理进行网络抓取&#xff1f; 总结 引言 在当今数据驱动的商业环境中&#xff0c;数据的获取和分析能力是企…

HttpMessageNotReadableException

项目本身用的全是JSON&#xff0c;但是对接MES的时候他们用的XML&#xff0c;就添加了对XML的支持&#xff0c;然后发现AGV发送任务的接口报下面的错误了。 Error while extracting response for type [class java.lang.String] and content type [application/json;charsetut…

77 智能卡ATR TA1通信速率计算

1 前言 智能卡读卡器在读卡前期会以默认标准通信速率9600与卡片交互&#xff0c;期间可通过卡片返回的ATR值中TA1字段获取卡片支持的最大通信速率&#xff0c;然后读卡器通过PPS指令与卡片协商更改通信速率&#xff0c;最后以协商的速率进行通信。 起初默认9600波特率是比较慢的…

图片高清修复怎么做?4种高清修复方法分享给你

照片已经成为我们记录生活、珍藏回忆的重要方式。然而&#xff0c;随着时间的推移&#xff0c;不少珍贵的照片可能因保存不当或拍摄技术限制而变得模糊不堪。想要将这些模糊的照片变清晰成为当下的急迫需求。不过不用担心&#xff0c;下面就来给大家分享4种高清修复图片方法&am…

TCP系列相关内容

一、TCP上传文件 loop——本地回环测试地址。 void *memset&#xff08;void *s,int c,size_t n&#xff09;——给一个变量设定一个值。 1、“粘包”问题 两次分别发送的数据&#xff0c;被一起接收形成该现象。 原因&#xff1a;TCP流式套接字&#xff0c;数据与数据间没…

超低排放验收流程的全方位指南

近年来&#xff0c;随着环保要求的不断升级&#xff0c;朗观视觉超低排放验收成为了众多工业企业必须面对的关键环节。本文将详细介绍超低排放验收流程的安装要求、最新政策、国家标准以及企业应对的解决方案&#xff0c;帮助企业更好地理解和应对这一重要课题。 一、超低排放验…

校园一卡通_q7e7o

TOC springboot576校园一卡通_q7e7o--论文 第一章 概述 1.1 研究背景 近些年&#xff0c;随着中国经济发展&#xff0c;人民的生活质量逐渐提高&#xff0c;对网络的依赖性越来越高&#xff0c;通过网络处理的事务越来越多。随着校园一卡通的常态化&#xff0c;如果依然采用…

JS中Promise用法(简要说明)

文章目录 1、下方自定义名词约定2、官方流程图3、构造函数Promise <状态>fulfilled 用法代码图示 4、构造函数Promise <状态>rejected 用法代码图示 5、第3和4结合使用&#xff0c;可以将promise状态settled为2种情况之一代码图示&#xff08;图中if和else都是调…

移动硬盘直接拔下来有什么影响吗?数据丢失如何恢复

在日常的工作与生活中&#xff0c;移动硬盘成为了我们不可或缺的数据存储和传输设备。然而&#xff0c;很多人或许都曾有过这样的经历&#xff1a;在数据传输或使用中&#xff0c;由于一时疏忽或赶时间&#xff0c;直接拔下了正在工作的移动硬盘。这样的行为&#xff0c;虽然看…

冷却液温度传感器检测诊断

检测发动机冷却液温度&#xff0c;向ECU输入温度信号&#xff0c;作为燃油喷射和点火正时的修正信号&#xff0c;同时也是其他控制系统的控制信号。 冷却液温度传感器安装位置 冷却液温度传感器&#xff08;俗称水温传感器&#xff09;一般安装在缸体水道上&#xff0c;缸盖水…

docker命令实现容器管理

容器镜像分类 1.系统类镜像 2.应⽤镜像 搜索镜像 下载镜像 默认下载最新版本 1.安装docker环境 #配置变量 2.启动并且使⽤ 2.配置远程管理 帮助和指令

JVM的五个 invoke 指令详解

文章目录 概述invoke 指令概览1. invokespecial2. invokevirtual3. invokestatic4. invokeinterface5. invokedynamic 总结 概述 Java 虚拟机 (JVM) 是 Java 语言的核心组件之一&#xff0c;负责执行 Java 字节码。在 JVM 中&#xff0c;invoke 指令用于执行方法调用。本文将详…

K8s 集群巡检

K8s 集群巡检 上次发文 K8s 无备份&#xff0c;不运维&#xff0c;文章开篇&#xff0c;插入了一张 K8s 集群巡检的图片&#xff0c;好多小伙伴私信留言&#xff0c;问我要开源地址。由于其通用性不高&#xff0c;大多数公司需要结合自身的架构情况进行不同的巡检&#xff0c;…

互联网应用主流框架整合之Redis配置

在实际的商用系统中&#xff0c;Redis常用的机制包括备份、回收策略、主从复制、哨兵模式、集群模式等&#xff0c;在保证性能的同时还要保证其高可用 首先要熟悉一下Redis的配置文件&#xff0c;如果实在linux系统中&#xff0c;配置文件是redis.conf&#xff0c;而在windows…

linux系统编程:网络通信

1.网络 1.粘包 tcp特点 面向连接 字节流&#xff08;TCP 将数据视为连续的字节流&#xff0c;没有明确的消息边界。会发生粘包问题。 避免粘包 特殊分隔符&#xff1a;在消息间加入特殊的分隔符&#xff08;如换行符或其他特殊字符&#xff09;&#xff0c;接收方根据分…

404炫酷单页面html5源码

源码介绍 404炫酷单页面html5源码&#xff0c;感觉应该符合一些人的感觉&#xff01;可以用来做404页面。记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 源码下载 分…

Java基础再学习

作为一名实习生&#xff0c;为了夯实基础、查缺补漏&#xff0c;我跟随 B 站学习了以下知识&#xff0c;欲将其留存纪念&#xff0c;故对其中内容进行优化&#xff0c;以使其更为优雅。 面向对象 面向对象编程的定义&#xff1a;借助合适的对象来解决问题&#xff08;如运用 …