如何重塑在C#中的数组 [英] How to reshape an Array in c#
问题描述
我有我已经从位图的读取在C#中的字节数组3D:
字节[W,H,3]
什么是最简单和重塑这个数组转换成2D(线性)的形式?
的性能更友好的方式 字节[W * H,3]
在换句话说,我想保持信道数(特征),但在一个直线形状(而不是方形)
让我试着说明输入所需的输出:
输入:
|(R1,G1,B1)(R2,G2,B2)(R3,G3,B3)|
|(R4,G4,B4)(R5,G5,B5)(R6,G6,B6)|
|(R7,G7,B7)(R8,G8,B8)(R9,G9,B9)|
注意,常用3 [0,0,0] = r1中,改编[0,0,1] = G1,ARR [0,0,2] = B1等。
和输出:
|(R1,G1,B1)(R2,G2,B2)(R3,G3,B3)(R4,G4,B4)(R5,G5,B5)(6- ,G6,B6)... |
这似乎很好地工作,因为数组的已经在正确的形状记忆的:
变种一个=新字节[2,2,2] {{{1,2},{3,4}},{{5,6},{7,8 }}};
变种B =新的字节[2 * 2,2]。//的sizeof(字节)显然是1这里,但我把它放在那里的文档
Buffer.BlockCopy(一,0,B,0,则为a.length *的sizeof(字节));
对于那些有兴趣:至于做什么,如果你真的想要的转的二维数组到1D:
字节[,] A = {
{1,2},
{3,4},
{5,6},
};
变种B =新的字节[a.GetLength(1)* a.GetLength(0)]; //移调const int的R_STRIDE1 = 8; //调整此为你的CPU
const int的C_STRIDE1 = 8; //调整此为你的CPU//你应该葫芦对GetLength()的调用圈外不像我在这里做
为(中间体R1 = 0; R 1所述; a.GetLength(0); R1 + = R_STRIDE1)
为(中间体C1 = 0; C1&下; a.GetLength(1); C1 + = C_STRIDE1)
为(中间体R2 = 0; R 2&下; R_STRIDE1; R ++)
为(中间体C2 = 0; C 2所述; C_STRIDE1; C2 +)
{
变种R = R1 + R2;
变种C = C1 + C2;
如果(为r a.GetLength(0)及&放大器;℃下a.GetLength(1))
B〔C * a.GetLength(0)+ R] = A [R,C]。
}
这应该利用缓存在CPU中。我的仅在此进行有限的测试 - 它仍然是缓慢的。尝试调整它,如果它是。结果
你可以(有点不平凡)这个扩展到三维数组。
I have a 3D array of bytes in c# which I have read from a bitmap:
byte[w, h, 3]
What is the easiest and more performance-friendly way of reshaping this array into 2D (linear) form?
byte[w*h, 3]
In other words I want to keep number of channels (features) but in a linear shape (rather than a square shape)
Let me try to illustrate input and desired output:
input:
|(r1,g1,b1) (r2,g2,b2) (r3,g3,b3)|
|(r4,g4,b4) (r5,g5,b5) (r6,g6,b6)|
|(r7,g7,b7) (r8,g8,b8) (r9,g9,b9)|
note that arr[0, 0, 0] = r1, arr[0, 0, 1] = g1, arr[0, 0, 2] = b1, etc..
and output:
|(r1,g1,b1) (r2,g2,b2) (r3,g3,b3) (r4,g4,b4) (r5,g5,b5) (r6,g6,b6) ...|
This seems to work fine, because the array is already in the right shape in memory:
var a = new byte[2, 2, 2] { { { 1, 2 }, { 3, 4 } }, { { 5, 6 }, { 7, 8 } } };
var b = new byte[2 * 2, 2];
//sizeof(byte) is obviously 1 here, but I put it there for documentation
Buffer.BlockCopy(a, 0, b, 0, a.Length * sizeof(byte));
For those interested: As for what to do if you really want to transpose a 2D array into 1D:
byte[,] a = {
{1, 2},
{3, 4},
{5, 6},
};
var b = new byte[a.GetLength(1) * a.GetLength(0)]; //Transpose
const int R_STRIDE1 = 8; //Tune this for your CPU
const int C_STRIDE1 = 8; //Tune this for your CPU
//You should hoist the calls to GetLength() out of the loop unlike what I do here
for (int r1 = 0; r1 < a.GetLength(0); r1 += R_STRIDE1)
for (int c1 = 0; c1 < a.GetLength(1); c1 += C_STRIDE1)
for (int r2 = 0; r2 < R_STRIDE1; r2++)
for (int c2 = 0; c2 < C_STRIDE1; c2++)
{
var r = r1 + r2;
var c = c1 + c2;
if (r < a.GetLength(0) && c < a.GetLength(1))
b[c * a.GetLength(0) + r] = a[r, c];
}
This should take advantage of caching in the CPU. I have only performed limited testing on this -- it could still be slow. Try tweaking it if it is.
You can (somewhat non-trivially) extend this to a 3D array.
这篇关于如何重塑在C#中的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!