Pythonのmatplotlibを使った鳥瞰図(birdview)の作り方

スポンサーリンク
Python/DeepLearning

こんにちは!みやしんです。

今回はPythonで鳥瞰図を作ってみましたので、メモ的に残したいと思います。

サンプルコード付ですのでコピペしてお使いください。

鳥瞰図って皆さんご存じですか?

地図とか人や車の流れを表現したりするときに、上空から見た感じにプロットする手法ですね!

空飛ぶ鳥の目線で描かれた地図のようなものです!

みやしん
みやしん

ドラゴンレーダーも鳥瞰図だにや!!

おお!確かにそうですね!ドラゴンレーダーってこれですね!

Amazon | PROPLICA ドラゴンボール ドラゴンレーダー 約100mm ABS製 塗装済み完成品フィギュア | フィギュア・ドール 通販

と、いうことで遊び心も含めまして、鳥瞰図をドラゴンレーダー風に作ってみたいと思います!

完成はこんな感じで動画にもしちゃいたいと思います。

サンプルデータやスクリプトも公開しておりますので、是非作ってみてくださいね^^。

あっ・・・、ちなみに何か願いをかなえたい方は、こちらもオススメです。

スポンサーリンク

ドラゴンレーダー風、鳥瞰図作成用データ

以下のリンクからドラゴンレーダー作成用のcsvファイルをダウンロードできます。

A列に時間、B列以降に7つのドラゴンボールの座標が記載されております。

DragonBallPositin.csv

ドラゴンレーダー風、鳥瞰図画像作成スクリプト (サンプルコード)

スクリプトは以下になります。

ドラゴンレーダーを作ってみたい方はコピペしてお使いください^^

スクリプトのファイル(DragonRadar.py)と同じ階層に「output」という名前のフォルダを作成ください。そこにドラゴンレーダー画像を1フレーム毎に出力します。

フォルダ構成

outputフォルダには、こんな感じでたくさんドラゴンレーダー風鳥瞰図の画像が出力されます。

スクリプトです。

ファイル名:DragonRadar.py

# coding;utf-8

# --- overview ---
# author      : miyashin
# description : DragonRadar
#

# --- import ---
import pandas as pd

# csvファイル DragonBallPosition.csv を読込む
def Readcsv(IndexNum):
    df = pd.read_csv('./DragonBallPosition.csv')
    row = df.loc[[IndexNum], :]
    return row
 

# 秒毎のドラゴンレーダー画像を作成、出力
def DragonRadarSnapshot(row, outputfile):

    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    import numpy as np

    plt.ioff() #インタラクティブモード(対話モード)offにより図の表示を回避

        
    # ドラゴンボールの座標を変数に格納
    ball1_X = row['ball1_X']
    ball1_Y = row['ball1_Y']

    ball2_X = row['ball2_X']
    ball2_Y = row['ball2_Y']
        
    ball3_X = row['ball3_X']
    ball3_Y = row['ball3_Y']
        
    ball4_X = row['ball4_X']
    ball4_Y = row['ball4_Y']
        
    ball5_X = row['ball5_X']
    ball5_Y = row['ball5_Y']
    
    ball6_X = row['ball6_X']
    ball6_Y = row['ball6_Y']
        
    ball7_X = row['ball7_X']
    ball7_Y = row['ball7_Y']

    ball_X = []
    ball_Y = []

    # 型をfloatに調整
    for i in [ball1_X, ball2_X, ball3_X, ball4_X, ball5_X, ball6_X, ball7_X]:
        ii = pd.to_numeric(i, downcast='float')
        iii = float(ii)
        ball_X.append(iii)


    for j in [ball1_Y, ball2_Y, ball3_Y, ball4_Y, ball5_Y, ball6_Y, ball7_Y]:
        jj = pd.to_numeric(j, downcast='float')
        jjj = float(jj)
        ball_Y.append(jjj)

    

    # --- Settings -----
    YLIM_MIN = -140
    YLIM_MAX = 140
    XLIM_MIN = -140
    XLIM_MAX = 140

    # ドラゴンレーダー画面を作る
    figsizeX = 5
    figsizeY = figsizeX 
    fig, ax = plt.subplots(figsize=(figsizeX, figsizeY), facecolor='black', subplot_kw=dict(facecolor='black'))
    ax.set_xticks(np.arange(-140, 141, 20)) # x軸に目盛設定
    ax.set_yticks(np.arange(YLIM_MIN, YLIM_MAX + 1, 20))
    
    ax.set_title("Dragon Radar", color="white")
    ax.set_xlabel("West <= | => East", color="white")
    ax.set_ylabel("South <= | => North", color="white")
    ax.spines['bottom'].set_color('white') # 軸の色設定
    ax.spines['top'].set_color('white')
    ax.spines['left'].set_color('white')
    ax.spines['right'].set_color('white')
    ax.tick_params(colors='white', grid_color='black')
    plt.grid(which='both', linewidth=0.25, linestyle='dotted')
    plt.xticks(fontsize=8)
    plt.yticks(fontsize=8)
    plt.xlim(XLIM_MAX, XLIM_MIN)
    plt.ylim(YLIM_MIN, YLIM_MAX)

    #ドラゴンレーダー上部のボタン部分を実装
    ax.add_patch(patches.Rectangle((-5, 115), 10, 5,
                                                    edgecolor='white',
                                                    facecolor='white',
                                                    linewidth=0.25,
                                                    fill=True)) 

    ax.add_patch(patches.Rectangle((-15, 120), 30, 10,
                                                    edgecolor='gray',
                                                    facecolor='white',
                                                    linewidth=0.25,
                                                    fill=True)) 

    ax.add_patch(patches.Rectangle((-10, 110), 20, 5,
                                                    edgecolor='gray',
                                                    facecolor='white',
                                                    linewidth=0.25,
                                                    fill=True))  


    # ドラゴンレーダーの白い枠を表示
    ax.add_patch(patches.Circle(xy=(0, 0), radius=110, facecolor='white', edgecolor='gray'))
    
    # ドラゴンレーダー画面を表示
    ax.add_patch(patches.Circle(xy=(0, 0), radius=95, facecolor='darkgreen', edgecolor='darkgreen'))

    # 自分の位置(原点)
    ax.add_patch(patches.Polygon(xy = [(0, 5), (-4.33, -2.5), (4.33, -2.5)],
                facecolor = "orangered", edgecolor = "red"))
    
    for a, b in zip(ball_X, ball_Y):
        if (a != 999) or (b != 999):
            ax.add_patch(patches.Circle(xy=(a, b), radius=3, facecolor='yellow', edgecolor='tomato'))
    
    # .pngファイルで保存
    plt.savefig(outputfile, dpi=150, transparent=False, facecolor=fig.get_facecolor())
    print(outputfile)

    # 図をクリア
    plt.clf()
    plt.cla()
    plt.close() #Figureモードオフ

    return outputfile


if __name__ == '__main__':
    for i in range(0,100): #100枚画像をアウトプット(10fpsで10秒)
        row = Readcsv(i)
        if i <= 9:
            outputfile = r'.\output\DragonRadar000' + str(i) + '.png'
        elif (i >= 10)and(i <= 99):
            outputfile = r'.\output\DragonRadar00' + str(i) + '.png'
        elif (i >= 100)and(i <= 999):
            outputfile = r'.\output\DragonRadar0' + str(i) + '.png'
        elif (i >= 1000)and(i <= 9999):
            outputfile = r'.\output\DragonRadar' + str(i) + '.png'

        DragonRadarSnapshot(row, outputfile)

出力した複数の画像から動画を作成する(cv2.VideoWriter)

以下のスクリプトを実行して出力した複数の画像を連結して動画にします。

outputフォルダー内にたくさんの画像と一緒にスクリプト(MakeMovie.py)を配置して実行します。

MakeMovie.py

import sys
import cv2

# encoder(for mp4)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
# output file name, encoder, fps, size(fit to image size)
video = cv2.VideoWriter('DragonRadar.mp4',fourcc, 10, (750, 750)) # 10fps

if not video.isOpened():
    print("can't be opened")
    sys.exit()

for i in range(0, 1132):
    # DragonRadar0000.png
    img = cv2.imread('./DragonRadar%04d.png' % i)

    # can't read image, escape
    if img is None:
        print("can't read")
        break

    # add
    video.write(img)
    print(i)

video.release()
print('written')

MakeMovie.pyを実行すると、この記事の最初にあったような動画にすることができます!

以上で完成、よし、ドラゴンボールを7つ集めて願いを叶えるにゃ!!!

合わせて読みたい

Python/DeepLearning
スポンサーリンク
記事が良かったらSNSでシェアを宜しくお願いします!
みやしんをフォローすると役立つ情報がいっぱいにゃ!
スポンサーリンク

コメント

タイトルとURLをコピーしました