如何重塑在C#中的数组 [英] How to reshape an Array in c#

查看:112
本文介绍了如何重塑在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆