NCNN 源码学习【三】:数据处理

一、Topic:数据处理

这次我们来一段NCNN应用代码中,除了推理外最重要的一部分代码,数据处理:

    ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR, bgr.cols, bgr.rows, 227, 227);const float mean_vals[3] = {104.f, 117.f, 123.f};in.substract_mean_normalize(mean_vals, 0);

这一部分代码由两部分组成:

  • from_pixels_resize:将cv::Mat数据转换到ncnn::Mat同时进行resize操作
  • substract_mean_normalize:这个就是减均值除方差

二、from_pixels_resize

先看名字,from_pixels_resize由两部分组成:

  1. from_pixels:从unsigned char* 的数组转换到 ncnn::Mat
  2. resize:unsigned char* 的数据下进行resize

源码中是先进行resize再进行from_pixels。

A、resize

这个代码支持三种图像类型:单通道的GRAY、三通道的RGB和BGR、四通道的RGBA。源码使用的都是bilinear插值,这里我们挑个简单的单通道GRAY的来看看,函数名字很直观,就叫做resize_bilinear_c1,后面的c1就是chennel 1的意思。具体的代码在mat_pixel.cpp的第1414行,这个我就不细说了,大家可以去看这个文章,这个虽然写的是TNN的,但仔细看下来会发现其实跟NCNN的实现是一样的(变量名也一样)。
在这里插入图片描述

这个大体流程就是:

  1. 先算x、y方向上插值点的位置索引xofs和yofs
  2. 再算x、y方向上插值点左右的两个插值稀疏iapha和ibeta
  3. 遍历插值,x方向上的插值用xofs和ialpha得到,y方向上的插值用yofs和ibeta得到

这个计算的细节还是很多的,大家感兴趣的可以去仔细研究一下,这里就不细写了,ncnn的代码为例效率,可能写的不是特别美观。

B、from_pixels

这个就很简单了,就是开辟一块ncnn::Mat的内存,然后遍历数组一个一个填进去就好了,同样的这里支持单通道、三通道、四通道,而且一些颜色转换RGB2BGR、RGB2GRAY这些都是实现支持的,我们挑一个典型的RGB2GRAY的实现来看,源码在mat_pixel.cpp的第539行,函数名就是from_rgb2gray。
在这里插入图片描述

static Mat from_rgb2gray(const unsigned char* rgb, int w, int h)
{const unsigned char Y_shift = 8;//14const unsigned char R2Y = 77;const unsigned char G2Y = 150;const unsigned char B2Y = 29;Mat m(w, h, 1);if (m.empty())return m;float* ptr = m;int size = w * h;int remain = size;for (; remain > 0; remain--){*ptr = (rgb[0] * R2Y + rgb[1] * G2Y + rgb[2] * B2Y) >> Y_shift;rgb += 3;ptr++;}return m;
}

这个代码很直观,前面就是定义了转换时R、G、B对应要乘的系数,这里作者用的是整数乘法,所以系数放大了28,后面算结果那里要右移回去。后面就是一个暴力for循环,全部遍历把数据塞进去ncnn::Mat就完了。但这里我还想放一下GRAY2RGB的代码,看下很值得注意的细节。

static Mat from_gray2rgb(const unsigned char* gray, int w, int h)
{Mat m(w, h, 3);if (m.empty())return m;float* ptr0 = m.channel(0);float* ptr1 = m.channel(1);float* ptr2 = m.channel(2);int size = w * h;int remain = size;for (; remain>0; remain--){*ptr0 = *gray;*ptr1 = *gray;*ptr2 = *gray;gray++;ptr0++;ptr1++;ptr2++;}return m;
}

从这个可以看出来,获取ncnn::Mat的三个通道的数据,是要用channel索引出来的,这里就是一个需要留意的点,ncnn::Mat的数据存储,channel间的需要对齐,不一定是连续的,也就是不要理所当然的用channel(0)的指针,自己加加加想去访问其他channel的数据,很容易翻车(我就因为这个翻车过),这个我们后面有时间可以好好写一写ncnn的数据排布。

三、substract_mean_normalize

substract_mean_normalize的源码在mat.cpp的第25行,这个代码是支持只mean不norm,只norm不mean,mean和norm都做得,由于这些都大同小异,我就直接贴都做mean和norm的代码了:

void Mat::substract_mean_normalize(const float* mean_vals, const float* norm_vals)
{int size = w * h;for (int q = 0; q < c; q++){float* ptr = data + cstep * q;const float mean = mean_vals[q];const float norm = norm_vals[q];int remain = size;for (; remain > 0; remain--){*ptr = (*ptr - mean) * norm;ptr++;}}
}

上面比较核心的就一句:

*ptr = (*ptr - mean) * norm;

就是遍历Mat的所有数据,给他减mean乘norm,要注意这里是乘norm,不是一般说的除方差,方差的倒数才是这里的norm。

参考&致谢:

https://zhuanlan.zhihu.com/p/456238585

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

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

相关文章

DDOS 攻击是什么?有哪些常见的DDOS攻击?

DDOS简介 DDOS又称为分布式拒绝服务&#xff0c;全称是Distributed Denial of Service。DDOS本是利用合理的请求造成资源过载&#xff0c;导致服务不可用&#xff0c;从而造成服务器拒绝正常流量服务。就如酒店里的房间是有固定的数量的&#xff0c;比如一个酒店有50个房间&am…

C# OpenVINO 直接读取百度模型实现图片旋转角度检测

目录 效果 模型信息 代码 下载 C# OpenVINO 直接读取百度模型实现图片旋转角度检测 效果 模型信息 Inputs ------------------------- name&#xff1a;x tensor&#xff1a;F32[?, 3, 224, 224] --------------------------------------------------------------- Ou…

RV32/64 特权架构

machine mode: 运行最可信的代码;supervisor mode:为 Linux&#xff0c;FreeBSD 和 Windows 等操作系统提供支持;user mode:权限最低&#xff0c;应用程序的代码在此模式下运行&#xff1b; 这两种新模式都比user mode有着更高的权限&#xff0c;有更多权限的模式通常可以使用…

算法:二叉树的遍历

一、31种遍历方法 (1)先序法&#xff08;又称先根法&#xff09; 先序遍历&#xff1a;根&#xff0c;左子树&#xff0c;右子树 遍历的结果&#xff1a;A&#xff0c;B&#xff0c;C 遍历的足迹&#xff1a;沿途经过各结点的“左部” (2)中序法&#xff08;又称中根法&#…

【Spark精讲】Spark内存管理

目录 前言 Java内存管理 Java运行时数据区 Java堆 新生代与老年代 永久代 元空间 垃圾回收机制 JVM GC的类型和策略 Minor GC Major GC 分代GC Full GC Minor GC 和 Full GC区别 Executor内存管理 内存类型 堆内内存 堆外内存 内存管理模式 静态内存管理 …

LV.13 D4 uboot使用 学习笔记

一、uboot环境变量命令 1.1 uboot模式 自启动模式 uboot 启动后若没有用户介入&#xff0c;倒计时结束后会自动执行自启动环境变量 (bootcmd) 中设置的命令&#xff08;一般作加载和启动内核&#xff09; 交互模式 倒计时结束之前按下任意按键 uboot 会进…

牛客后端开发面试题1

滴滴2022 1.redis过期策略 定时删除&#xff0c;定期删除&#xff0c;惰性删除 定时删除&#xff1a;设定一个过期时间&#xff0c;时间到了就把它删掉&#xff0c;对cpu不太友好&#xff0c;但是对内存友好 定期删除&#xff1a;每隔一个周期删除一次&#xff0c;对cpu和内存…

软件开发模型学习整理——瀑布模型

一 前言 从参加工作至今也完整的跟随过一整个项目的流程了&#xff0c;从中也接触到了像瀑布模型&#xff0c;迭代模型&#xff0c;快速开发模型等。介于此&#xff0c;基于自己浅薄的知识对瀑布模型进行整理学习以及归纳。 二 瀑布模型简介 2.1 瀑布模型的定义和特点 定义&…

这应该是最全的大模型训练与微调关键技术梳理

作为算法工程师的你是否对如何应用大型语言模型构建医学问答系统充满好奇&#xff1f;是否希望深入探索LLaMA、ChatGLM等模型的微调技术&#xff0c;进一步优化参数和使用不同微调方式&#xff1f;现在我带大家领略大模型训练与微调进阶之路&#xff0c;拓展您的技术边界&#…

动态规划习题

动态规划的核心思想是利用子问题的解来构建整个问题的解。为此&#xff0c;我们通常使用一个表格或数组来存储子问题的解&#xff0c;以便在需要时进行查找和使用。 1.最大字段和 #include <iostream> using namespace std; #define M 200000int main() {int n, a[M], d…

死锁 + 条件变量 + 生产消费者模型

文章目录 死锁如何解决死锁问题呢&#xff1f;避免死锁 同步概念1.快速提出解决方案 --- 条件变量原理接口2. CP问题 --- 理论3. 快速实现CP 死锁 现象 &#xff1a; 代码不会继续往后推进了 问题 一把锁有没有可能产生死锁呢&#xff1f; 有可能 线程第一次申请锁成功&…

【node】使用 sdk 完成短信发送

实现效果 过程 流程比较复杂&#xff0c;加上需要实名认证&#xff0c;建议开发的时候先提前去认证号账号&#xff0c;然后申请模版也需要等认证。 源码 我看了新版的sdk用的代码有点长&#xff0c;感觉没必要&#xff0c;这边使用最简单的旧版的sdk。 https://github.com/…

智能优化算法应用:基于秃鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于秃鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于秃鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.秃鹰算法4.实验参数设定5.算法结果6.参考文献7.MA…

基于ssm电子资源管理系统源码和论文

idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 环境&#xff1a; jdk8 tomcat8.5 基于ssm电子资源管理系统源码和论文758 摘要 随着互联网技术的高速发展&#xff0c;人们生活的各方面都受到互联网技术的影响。现在人们可以通过互联网技术就能实现不出家门…

jmeter,http cookie管理器

Http Cookie管理器自动实现Cookie关联的原理&#xff1a; (默认:作用域在同级别的组件) 一:当Jmeter第1次请求服务器的时候,如果说服务器有通过响应头的Set-Cookie有返回Cookie,那么Http Cookie管理器就会自动的保存这些Cookie的值。 二&#xff1a;当Jmeter第2-N次请求服务器的…

Redis 过期删除策略、内存回收策略、单线程理解

不知从何开始Redis的内存淘汰策略也开始被人问及&#xff0c;卷&#xff01;真的是太卷了。难不成要我们去阅读Redis源码吗&#xff0c;其实问题的答案&#xff0c;在Redis中的配置文件中全有&#xff0c;不需要你阅读源码、这个东西就是个老八股&#xff0c;估计问这个东西是想…

HNU-计算机网络-实验3-应用层和传输层协议分析(PacketTracer)

计算机网络 课程基础实验三应用层和传输层协议分析&#xff08;PacketTracer&#xff09; 计科210X 甘晴void 202108010XXX 【给助教的验收建议】 如果是助教&#xff0c;比起听同学读报告&#xff0c;更好的验收方式是随机抽取一个场景&#xff08;URL/HTTPS/FTP&#xff09…

Vue3-12- 【v-for】循环一个整数

说明 v-for 这个东西就很神奇&#xff0c;可以直接循环一个整数&#xff0c;而且循环的初始值是从1 开始。使用案例 <template><div v-for"(num,indexB) in 6" :key"indexB">【索引 {{ indexB }}】 - 【数字 {{ num }}】 </div></t…

直播传媒公司网站搭建作用如何

直播已然成为抖快等平台的主要生态之一&#xff0c;近些年主播也成为了一种新行业&#xff0c;相关的mcn机构直播传播公司等也时有开业&#xff0c;以旗下主播带来高盈利&#xff0c;而在实际运作中也有一些痛点难题&#xff1a; 1、机构宣传展示难 不少散主播往往会选择合作…

湖农大邀请赛shell_rce漏洞复现

湖农大邀请赛 shell_rce 复现 在 2023 年湖南农业大学邀请赛的线上初赛中&#xff0c;有一道 shell_rce 题&#xff0c;本文将复现该题。 题目内容&#xff0c;打开即是代码&#xff1a; <?phpclass shell{public $exp;public function __destruct(){$str preg_replace…