2017-07-06 9 views
0

私は自分のプライの輸出業者を作ったし、それが働いていてもかなり遅いです。私は、問題が具体的に要素をループして、this commentに基づいて、struct.packを使用してから来ると仮定しています。numpyデータをバイナリ形式でファイルに書き出します。プライジェネレータ

Nodesをエクスポートする際の課題は、それがタプルの1Dベクトルであることです。 Facesをエクスポートする際の課題は、の各行の前に、uchar形式の数字「3」が付いていることです。

コード全体をMWEとして使用しています。また、コードを使用してメッシュをプライ形式でエクスポートする場合は、参照コードを使用します。

コード:

from __future__ import division 
import numpy as np 
import struct 
import timeit 

def Timeme(funct,var,NN=10,NNN=10): 
    for i in xrange(NN): 
     start =timeit.default_timer() 
     for t in xrange(NNN): 
      funct(*var) 
     end =timeit.default_timer() 
     print str(i)+': '+str((end - start)/NNN*1000) 

# This function is fictitious. In reality the 
# Nodes array is imported from another module 
def MakeNodes(Nr,Nc): 
    Nodes=np.zeros(Nr*Nc,dtype=[('x', np.float32), ('y', np.float32), ('z', np.float32)]) 
    x = np.linspace(0, (Nc-1), Nc, dtype=np.float32) 
    y = np.linspace((Nr-1),0 , Nr, dtype=np.float32) 
    xv, yv = np.meshgrid(x, y, sparse=False, indexing='xy') 
    Nodes['x']=xv.flatten() 
    Nodes['y']=yv.flatten() 
    Nodes['z']=(1/2-((Nodes['x']/Nc-1/2)**2+ (Nodes['y']/Nr-1/2)**2))*Nr/2 
    return Nodes 

# Function below explained in https://stackoverflow.com/questions/44934631 
def MakeFaces(Nr,Nc): 
    out = np.empty((Nr-1,Nc-1,2,3),dtype=int) 
    r = np.arange(Nr*Nc).reshape(Nr,Nc) 
    l1=r[:-1,:-1] 
    l2=r[:-1,1:] 
    l3=r[1:,:-1] 
    l4=r[1:,1:] 
    out[:,:, 0,0] = l2 
    out[:,:, 0,1] = l1 
    out[:,:, 0,2] = l3 
    out[:,:, 1,0] = l4 
    out[:,:, 1,1] = l2 
    out[:,:, 1,2] = l3 
    out.shape =(-1,3) 
    return out 

def ExportPlyBinary(Nodes,Faces,file): 
    LN=len(Nodes) 
    LF=len(Faces) 

    header= \ 
    "ply\n" \ 
    "format binary_little_endian 1.0\n" \ 
    "element vertex "+str(LN)+"\n" \ 
    "property float x\n" \ 
    "property float y\n" \ 
    "property float z\n" \ 
    "element face "+str(LF)+"\n" \ 
    "property list uchar int vertex_indices\n" \ 
    "end_header\n" 

    with open(file, 'wb') as fp: 
     fp.write(header) 
     s = struct.Struct('<fff') 
     for nd in Nodes: 
      fp.write(s.pack(nd['x'],nd['y'],nd['z'])) 

     s = struct.Struct('<Blll') 
     for fc in Faces: 
      fp.write(s.pack(3,fc[0],fc[1],fc[2])) 

Nr=200 
Nc=200 
Nodes=MakeNodes(Nr,Nc) 
Faces=MakeFaces(Nr,Nc) 
Timeme(ExportPlyBinary,(Nodes,Faces,"Test.ply")) 
Timeme(np.savez,("Test_np.ply", Nodes,Faces)) 

結果:

0: 366.3528
1: 386.216017627 
2: 383.307741944 
3: 359.598214393 
4: 363.434228045 
5: 397.255473919 
6: 433.967095136 
7: 407.806616677 
8: 393.701390596 
9: 379.542319143 
0: 15.5258007875 
1: 13.2543344563 
2: 12.8754439597 
3: 24.2303215372 
4: 15.9684973291 
5: 14.2023306048 
6: 13.7465456437 
7: 13.6964054484 
8: 21.27484093 
9: 13.2139143373 

答えて

0

@ max9111で提案されているようにTrimeshをチェックし、より効率的な機能を作成することができました。重要なアイデアは、(1)新しい配列を作成して正しいデータ型と順序に変換し、(2).tostring関数を使用することです。私は当初は記憶を浪費するように見えるので、この方向を避けましたが、この時点で利点は明らかです。私のNodesアレイには.tostringが適用される準備ができていることに注意してください。しかし、私は解決策をより一般的に保ちますが。

def NewExportPlyBinary(Nodes,Faces,file): 
    LN=len(Nodes) 
    LF=len(Faces) 

    header= \ 
    "ply\n" \ 
    "format binary_little_endian 1.0\n" \ 
    "element vertex "+str(LN)+"\n" \ 
    "property float x\n" \ 
    "property float y\n" \ 
    "property float z\n" \ 
    "element face "+str(LF)+"\n" \ 
    "property list uchar int vertex_indices\n" \ 
    "end_header\n" 

    dtype_vertex = [('vertex', '<f4', (3))] 
    vertex = np.empty(LN, dtype=dtype_vertex) 
    vertex['vertex']=np.stack((Nodes['x'],Nodes['y'],Nodes['z']),axis=-1) 

    # vertex=Nodes 

    dtype_face = [('count', '<u1'),('index', '<i4', (3))] 
    faces = np.empty(LF, dtype=dtype_face) 
    faces['count'] = 3 
    faces['index'] = Faces 

    with open(file, 'wb') as fp: 
     fp.write(header) 
     fp.write(vertex.tostring()) 
     fp.write(faces.tostring()) 

私は今、200×200例えば、次の回を取得:

0: 373.361611377 # original ExportPlyBinary 
0: 20.5686725792 # numpy's savez 
0: 4.85469689001 # NewExportPlyBinary 

注:問題のサイズが増加savezNewExportPlyBinaryの違いは基本的に消失します。

1

利用可能なものは使用しないのはなぜ?

たとえば、trimesh? https://pypi.python.org/pypi/trimesh

パッケージのほんの一部ではない場合でも、ソースコードからこの部分をコピーして調整することができます。 (もちろん著者に言及すると)

+0

ありがとうございます。私はtrimeshを探索することで高速な解決策を得ることができました。 – Miguel

関連する問題