Wang 's treasure house


  • Home

  • Tags

  • Categories

  • Archives

  • About

  • Commonweal 404

  • Search

关于Tensorflow、Pytorch、Ncnn中NCHW通道的总结

Posted on 2021-09-05 | In 科研笔记 , 论文部分 | | Visitors:

目前深度学习训练和推理涉及到的输入数据通常为4-D,对应的通道格式主要有两种:

  1. NCHW
  2. NHWC

其中各个字母代表的含义为:

  • N - Batch
  • C - Channel 特征图通道
  • H - Height 特征图高度
  • W - Width 特征图宽度

各个框架和图像处理方式对图像数据要求如下:

  • TensorFlow模型默认的输入格式为:RGB NHWC
  • Pytorch模型默认的输入格式为:RGB NCHW
  • ONNX模型默认的输入格式为:RGB NCHW fp32
  • Caffe 的Blob通道顺序是:NCHW
  • TensorRT中通道顺序:NCHW
  • OpenCV默认数据格式为:BGR HWC uint8

NCHW 则是 Nvidia cuDNN 默认格式,使用 GPU 加速时用 NCHW 格式速度会更快

一、基本原理

如图所示,假定N = 2,C = 16,H = 5,W = 4,
无论逻辑表达上是几维的数据,在计算机中存储时都是按照1D来存储的。下面很可以很清楚的看到NCHW和NHWC格式的高位数据,存储为1D时候的样子:
NCHWandNHWC

总的来说,无论是NCHW还是NHWC或者CHWN,在读取为1D时都是从后往前读,举例来说:

  • 对于NCHW格式的4D数据,首先取W方向数据;然后H方向;再C方向;最后N方向。
    所以,序列化出1D数据为:
    000 (W方向) 001 002 003,(H方向) 004 005 … 019,(C方向) 020 … 318 319,(N方向) 320 321 …

  • 对于NHWC格式的4D数据,首先取C方向数据;然后W方向;再H方向;最后N方向。
    所以,序列化出1D数据:
    000 (C方向) 020 … 300,(W方向) 001 021 … 303,(H方向) 004 … 319,(N方向) 320 340 …

我们通常在输入一张256 * 256分辨率的rgb图像时,对应的4D数据为[N = 1, H=256.h, W=256, C=3],然后对应的1D数据的组织方式如下图所示:
Rgb_NCHW_NHWC

NCHW: RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB

NHWC: RBGRGBRGBRGBRGBRGBRGBRGBRGBRGB

二、java调用tensorflow pb模型推理的简单运用

第一种,若 Tensor.create(input) 输入的input是4维数组,那么按照tensorflow要求的NHWC的格式进行数据的组织即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
Imgproc.resize(src, dst, new Size(h, w)); // 1, h, w,3
float input[][][][] = new float[1][h][w][3];
System.out.println(dst.rows());
System.out.println(dst.cols());
for (int i = 0; i < dst.cols(); i++) {
for (int j = 0; j < dst.rows(); j++) {
double[] pixel = dst.get(j, i);
input[0][i][j][0] = (float) (255 - pixel[0]);
input[0][i][j][1] = (float) (255 - pixel[1]);
input[0][i][j][2] = (float) (255 - pixel[2]);
}
}
Tensor input_X = Tensor.create(input);

第二种,若 Tensor.create(input) 输入的input是1维数组,那么按照前面转1D数据的基本原理,将NHWC的格式进行转换后再组织即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Imgproc.resize(src, dst, new Size(h, w)); // 1, h, w,3
float input[] = new float[1 * h * w * 3];
System.out.println(dst.rows());
System.out.println(dst.cols());
int index = 0;
for (int i = 0; i < dst.cols(); i++) {
for (int j = 0; j < dst.rows(); j++) {
double[] pixel = dst.get(j, i);
input[index++] = (float) (255 - pixel[0]);
input[index++] = (float) (255 - pixel[1]);
input[index++] = (float) (255 - pixel[2]);
}
}
Tensor input_X = Tensor.create(shape = (1,h,w,3),input);

LeetCode刷题之旅(16)--最接近的三数之和(中等题)

Posted on 2019-07-23 | In 算法 , LeetCode刷题之旅 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:最接近的三数之和

1
2
3
4
5
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
Read more »

LeetCode刷题之旅(11)--盛最多水的容器(中等题)

Posted on 2019-07-23 | In 算法 , LeetCode刷题之旅 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:盛最多水的容器

1
2
3
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

question_11

1
2
3
4
5
6
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49

Read more »

LeetCode刷题之旅(15)--正则表达式匹配(困难题)

Posted on 2019-06-14 | In 算法 , LeetCode刷题之旅 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:正则表达式匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:

输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:

输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:

输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:

输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
Read more »

【科研笔记】CTeX的套件中MiKTeX版本太低,无法更新包的解决办法

Posted on 2018-12-11 | In 科研笔记 , 论文部分 | | Visitors:

当前CTeX套装中的MiKTeX过于陈旧,很多宏包已经无法自动更新了。因此,需要重新安装新版MiKTeX来解决问题。

工具准备:

(1)CTeX套装: CTeX_2.9.2.164_Full.exe ,网址:www.ctex.org/CTeXDownload
务必选择Full版本

(2)下载最新版 MiKTeX:basic-miktex-2.9.6753-x64.exe ,网址
MiKTeX

Read more »

算法作业1-右移数组

Posted on 2018-11-26 | In 算法 , 作业练习 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:右移数组

1
已知一个长度为 n 的数组和一个正整数 k,并且最多只能使用一个用于交换数 组元素的附加空间单元,试设计算法得到原数组循环右移 k 次的结果并分析算法的时间复杂度。
Read more »

算法作业3-多米诺骨牌

Posted on 2018-11-26 | In 算法 , 作业练习 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:多米诺骨牌

1
2
现有 n 块 “多米诺骨牌” s1; s2; 。 。 。 ; sn 水平放成一排,每块骨牌 si 包含左右两 个部分,每个部分赋予一个非负整数值,如下图所示为包含 6 块骨牌的序列。骨牌可做 180 度旋转,使得原来在左边的值变到右边,而原来在右边的值移到左边,假设不论 si 如何
旋转,L[i] 总是存储 si 左边的值,R[i] 总是存储 si 右边的值,W [i] 用于存储 si 的状态: 当 L[i] <=R[i] 时记为 0,否则记为1,试采用分治法设计算法
Read more »

LeetCode刷题之旅(14)--最长公共前缀(简单题)

Posted on 2018-11-19 | In 算法 , LeetCode刷题之旅 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:最长公共前缀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

示例 1:

输入: ["flower","flow","flight"]
输出: "fl"
示例 2:

输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:

所有输入只包含小写字母 a-z 。
Read more »

LeetCode刷题之旅(13)--罗马数字转整数(简单题)

Posted on 2018-11-19 | In 算法 , LeetCode刷题之旅 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:罗马数字转整数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

示例 1:

输入: "III"
输出: 3
示例 2:

输入: "IV"
输出: 4
示例 3:

输入: "IX"
输出: 9
示例 4:

输入: "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:

输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
Read more »

LeetCode刷题之旅(12)--整数转罗马数字(中等题)

Posted on 2018-11-19 | In 算法 , LeetCode刷题之旅 | | Visitors:

每天属于自己的时间,就是慢慢的刷题的时候,啥也不用想,沉浸在写出最佳程序的过程中,沉浸在自己阅读大牛代码,提升自我的过程中,那种满足感,真的很让人享受<.>

题目:整数转罗马数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

示例 1:

输入: 3
输出: "III"

示例 2:

输入: 4
输出: "IV"
示例 3:

输入: 9
输出: "IX"
示例 4:

输入: 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.
示例 5:

输入: 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.
Read more »
12…4
Chaoqun Wang

Chaoqun Wang

Stay Hungry,Stay Foolish

39 posts
8 categories
82 tags
GitHub E-Mail Coding QQ
© 2021 Chaoqun Wang
本站访客数: | Hosted by Coding Pages 鄂ICP备16002360号-1
|
Powered by Hexo
|
Theme — NexT.Pisces v5.1.4