Python (ファイル入出力)

Obj ファイルの入出力

  1. 以下のスクリプトを、scale.py というファイル名で保存します。
    #!env python
    import sys
    
    infp = open(sys.argv[1], 'r')
    outfp = open(sys.argv[2], 'w')
    for line in infp.readlines():
        s = line.split()
        if len(s) < 1:
            continue
        if s[0] == 'v':
            x = 2*float(s[1])
            y = 2*float(s[2])
            z = 2*float(s[3])
            outfp.write('v ' + str(x) + ' ' + str(y) + ' ' + str(z) + '\n')
        else:
            outfp.write(line)
    infp.close()
    outfp.close()
    
  2. 以下のように実行します。
    # python scale.py cube1.obj cube2.obj
    cube1.obj

    cube2.obj

    cube1.obj のObjデータ
    cube2.obj のObjデータ

スクリプト解説

infp = open(sys.argv[1], 'r')
入力ファイルをオープンします。
outfp = open(sys.argv[2], 'w')
出力ファイルをオープンします。
for line in infp.readlines():
入力ファイルから1行ずつ読み込んでループを実行します。
s = line.split()
1行分のデータを空白を区切りとして、分割しリストにします。
if len(s) < 1:
リストの要素数が0なら、空行です。
continue
空行の場合は何もしないで、すぐに次の行の処理に移ります。
if s[0] == 'v':
リストの0番目の要素が'v'なら、頂点座標データなので計算処理を行います。
x = 2*float(s[1])
y = 2*float(s[2])
z = 2*float(s[3])
X, Y, Z座標の値をそれぞれ2倍にします。
sの要素はすべて文字列なので、float()によって実数値に変換して計算を行います。
outfp.write('v ' + str(x) + ' ' + str(y) + ' ' + str(z) + '\n')
出力ファイルに計算結果を書き込みます。
変数x, y, zの値は数値なので、str()によって文字列に変換して書き込みます。 
  else:
outfp.write(line)
頂点座標データ以外は、そのまま出力ファイルに書き込みます。
infp.close()
outfp.close()
入出力ファイルを閉じます。

画像合成

画像合成をマスクを使用して処理するスクリプトです。
入力画像ファイルの解像度はすべて同じという前提で作成してあります。

  1. 以下のスクリプトを、composite.py というファイル名で保存します。
    #!env python
    import sys
    import struct
    
    destfile = open(sys.argv[1], 'r')
    srcfile = open(sys.argv[2], 'r')
    maskfile = open(sys.argv[3], 'r')
    outfile = open(sys.argv[4], 'w')
    
    for i in range(3):
        d = destfile.readline()
        outfile.write(d)
        srcfile.readline()
        maskfile.readline()
    
    destdata = destfile.read()
    srcdata = srcfile.read()
    maskdata = maskfile.read()
    
    odata = ''
    for i in range(len(destdata)/3):
        rn = 3*i
        gn = rn + 1
        bn = rn + 2
    
        r1 = ord(destdata[rn])
        g1 = ord(destdata[gn])
        b1 = ord(destdata[bn])
        r2 = ord(srcdata[rn])
        g2 = ord(srcdata[gn])
        b2 = ord(srcdata[bn])
        r3 = ord(maskdata[rn])/255.0
        g3 = ord(maskdata[gn])/255.0
        b3 = ord(maskdata[bn])/255.0
    
        r = r1*(1.0 - r3) + r2*r3
        g = g1*(1.0 - g3) + g2*r3
        b = b1*(1.0 - b3) + b2*r3
        odata += struct.pack('BBB', r, g, b)
    
    outfile.write(odata)
    
    destfile.close()
    srcfile.close()
    maskfile.close()
    outfile.close()
    
  2. サンプルの画像をバイナリのppmファイルで用意します。
    (下の画像 tmp3.ppm)
    [tmp3.ppm]
    (上の画像 tmp4.ppm)
    [tmp4.ppm]
    (マスク画像 mask1.ppm)
    [mask1.ppm]
  3. 以下のように実行すると、tmp5.ppm の画像になります。
    # python composite.py tmp3.ppm tmp4.ppm mask1.ppm tmp5.ppm
    [tmp5.ppm]

スクリプト解説

destfile = open(sys.argv[1], 'r')
srcfile = open(sys.argv[2], 'r')
maskfile = open(sys.argv[3], 'r')
outfile = open(sys.argv[4], 'w')
入出力ファイルをオープンします。
for i in range(3):
ヘッダ部分を処理するために3回ループします。
d = destfile.readline()
outfile.write(d)
入力ファイルの一つからヘッダ部分を読み込み、そのまま出力ファイルに出力します。
srcfile.readline()
maskfile.readline()
他のファイルはヘッダ部分を読み飛ばします。
destdata = destfile.read()
srcdata = srcfile.read()
maskdata = maskfile.read()
入力ファイルのデータをすべて読み込みます。
odata = ''
出力データ用の変数odataをからの文字列で初期化します。
for i in range(len(destdata)/3):
読み込んだデータの1/3が、色データを処理する回数になります。
rn = 3*i
gn = rn + 1
bn = rn + 2
RGBのデータが入っているインデックスを計算します。
r1 = ord(destdata[rn])
g1 = ord(destdata[gn])
b1 = ord(destdata[bn])
r2 = ord(srcdata[rn])
g2 = ord(srcdata[gn])
b2 = ord(srcdata[bn])
r3 = ord(maskdata[rn])/255.0
g3 = ord(maskdata[gn])/255.0
b3 = ord(maskdata[bn])/255.0
入力ファイルからRGBのデータを変数に代入します。
入力データは文字になっているので、ord()で数値に変換します。
マスクの数値を255.0で除算しているのは、 0.0〜1.0に正規化するためです。 
r = r1*(1.0 - r3) + r2*r3
g = g1*(1.0 - g3) + g2*r3
b = b1*(1.0 - b3) + b2*r3
画像データをマスクによって合成する計算です。
odata += struct.pack('BBB', r, g, b)
計算された数値を1バイトずつ計3バイトのデータにして、 odataに追加します。
outfile.write(odata)
合成済みのデータを出力ファイルに書き込みます。
destfile.close()
srcfile.close()
maskfile.close()
outfile.close()
各ファイルを閉じます。

練習問題

  1. Objファイルを読み込んで、オブジェクトを原点中心に回転させるスクリプトrotate.pyを作成してみましょう。
    読み込むファイル名は、コマンドラインで指定します。
    例えば、以下のように実行するとcube1.objの原点中心にX軸中心に30度、 Y軸中心に60度、Z軸中心に45度回転されたデータがcube3.objに出力されます。
    # python rotate.py 30 60 45 cube1.obj cube3.obj
    cube1.obj (回転前)

    cube3.obj (回転後)

参考


Prev
index | home
abetmhr@gmail.com