2016-06-16 14 views
1

画像の3D表現をスライスしようとしています。既知の因子である次3D画像のスライシング

  • DimensionX
  • DimensionY
  • DimensionZ
  • ボクセル[]

ボクセル[]は、画素の階調を表すushortsのアレイです。

Presentation of image

今、私はすべての可能な方向にそれをスライスする必要があります。 x、y、zといってみましょう。

X-Slice

Z-SliceY-Slice私はこのために木の実装を持っていますが、彼らは一つの問題を持って、彼らは同じではありません寸法では動作しません。 (Zスライスを除いて、これは完全に動作しています)。

これらはメソッドです:

private ushort[] GetZSlice(int z, ushort[] voxels, int DimensionX, int DimensionY) 
{ 
    var res = new ushort[DimensionX * DimensionY]; 
    for(int j = 0; j < DimensionY; j++) 
    { 
     for(int i = 0; i < DimensionX; i++) 
     { 
      res[j*DimensionX + i] = voxels[z*DimensionX*DimensionY + j*DimensionX + i]; 
     } 
    } 
    return res; 
} 

この方法は完全に働いている、それは私がディメンションとして選択メイザーワットません。

深度としてxまたはyを使用する次の2つの方法は、より困難な問題となります。

private ushort[] GetYSlice(int y, ushort[] voxels, int DimensionX, int DimensionY, int DimensionZ) 
{ 
    var res = new ushort[DimensionX * DimensionZ]; 
    for(int i = 0; i < DimensionX; i++) 
    { 
     for(int j = 0; j < DimensionX; j++) 
     { 
      res[j + i*DimensionX] = voxels[j * DimensionZ * DimensionY + Y*DimensionZ + i] 
     } 
    } 
    return res; 
} 

private ushort[] GetXSlice(int x, ushort[voxels], int DimensionX, int DimensionY, int DimensionZ) 
{ 
    var res = new short[DimensionY * DimensionZ]; 
    for(int i = 0; i < DimensionY; i++) 
    { 
     for(int j = 0; j < DimensionZ; j++) 
     { 
      res[j + i*DimensionZ] = voxels[i*DimensionY + j*DimensionZ*DimensionX + x] 
     } 
    } 
    return res; 
} 

最後の2つの方法を改善して、等しくない寸法でも機能する方法を教えてください。

答えて

1

基礎ベクトルを使ってユニバーサルスライス関数を作成してみませんか?管理するコードがはるかに少なくなります。

基本的にU,V軸がそれぞれX,YまたはZにマッピングされています。スライスWは未使用の3番目の軸です。だからあなたはU、Vをループし、Wのままにしておきます。各U,Vは、x,y,z座標の増分変化を表す基本ベクトル(ux,uy,uz),(vx,vy,vz)を有する。

私はあなたはそれが非常に素晴らしく、シンプルで見ることができるように class

//--------------------------------------------------------------------------- 
class LED_cube 
    { 
public: 
    int xs,ys,zs,***map; 

    LED_cube()    { xs=0; ys=0; zs=0; map=NULL; } 
    LED_cube(LED_cube& a) { xs=0; ys=0; zs=0; map=NULL; *this=a; } 
    ~LED_cube()    { _free(); } 
    LED_cube* operator = (const LED_cube *a) { *this=*a; return this; } 
    LED_cube* operator = (const LED_cube &a); 
    void _free(); 
    void resize(int _xs,int _ys,int _zs); 
    void cls(int col);         // clear cube with col 0x00BBGGRR 
    void sphere(int x0,int y0,int z0,int r,int col); // draws sphere surface with col 0x00BBGGRR 
    void slice (char *uv,int slice,int col);   // draws (XY,XZ,YZ) slice with col 0x00BBGGRR 
    void glDraw();          // render cube by OpenGL as 1x1x1 cube at 0,0,0 
    }; 
//--------------------------------------------------------------------------- 
void LED_cube::slice(char *uv,int slice,int col) 
    { 
    // detect basis vectors from uv string 
    int ux=0,uy=0,uz=0,us=0; 
    int vx=0,vy=0,vz=0,vs=0; 
    int x=slice,y=slice,z=slice,u,v,x0,y0,z0; 
    if (uv[0]=='X') { x=0; ux=1; us=xs; } 
    if (uv[0]=='Y') { y=0; uy=1; us=ys; } 
    if (uv[0]=='Z') { z=0; uz=1; us=zs; } 
    if (uv[1]=='X') { x=0; vx=1; vs=xs; } 
    if (uv[1]=='Y') { y=0; vy=1; vs=ys; } 
    if (uv[1]=='Z') { z=0; vz=1; vs=zs; } 
    // render slice 
    if ((x>=0)&&(x<xs)&&(y>=0)&&(y<ys)&&(z>=0)&&(z<zs)) 
    for (u=0;u<us;u++,x+=ux,y+=uy,z+=uz) 
     { 
     x0=x; y0=y; z0=z; 
     for (v=0;v<vs;v++,x+=vx,y+=vy,z+=vz) 
      map[x][y][z]=col; 
     x=x0; y=y0; z=z0; 
     } 
    } 
//--------------------------------------------------------------------------- 

... C++に私のLEDキューブにそれをエンコード...、まだはるかに最適化することができます。ここでは使用状況や出力例:あなたはあなたのボクセルはその後、ちょうどx,y,zからアドレスを計算1次元配列に格納されてしまったよう

cube.resize(32,16,20); 
cube.cls(0x00202020); 
cube.slice("XY",5,0x000000FF); 
cube.slice("XZ",5,0x0000FF00); 
cube.slice("YZ",5,0x00FF0000); 
cube.glDraw(); 

example

。だからmap[x][y][z]はあなたのvoxels[(x*ys*zs)+(y*zs)+z]になりました。これは基本ベクトルに完全にエンコードされるので、du=(ux*ys*zs)+(uy*zs)+uzdv=...を持ち、後で乗算を必要としないアドレスを直接増やすことができます。

+0

大変ありがとうございました。 – Gulpener