YutaKaのPython教室

Python の文法やライブラリ、API、環境構築について画像・動画・ソースコード付きで徹底解説!

【図解で解説】白色部分を透明化処理|Python×OpenCV

Pythonの画像処理ライブラリOpenCVを使用して、画像の白色部分を透明化する方法を紹介します。

正直言って、白色部分を透明化処理するだけであれば、ウェブ上に無料のソフトがあります。

しかし、自分でスクリプトを書けば、複数ファイルの自動処理など、応用の幅が広がります

とはいえ、いざやってみようとすると難しいものです。

そこで今回は、OpenCVを使用した白色部分の透明化処理について紹介します。

透明化処理とは?

画像データは、BGR(青緑赤)の3つのデータの重ね合わせで構成されます。

しかし、BGRに加えて透明度、アルファチャンネル(Alpha)を併せ持つ画像もあります。

透明度を持つ画像は、BGRA(青緑赤透明度)の4つのデータの重ね合わせです。

次の画像は背景が、白色と透明の場合の違いを表しています。

左側の元画像は同じ見た目ですが、他の画像に重ねた時に透明だと裏側が透けて見えます

画像を重ねる際に、背景が透明化どうかは大切になってきますね。

以下ではOpenCVを使用して、白色を透明化する方法を解説します。

OpenCV環境の準備

まずはじめに、PythonでOpenCVを使用できる環境を整えましょう。

ここではAnacondaでOpenCV環境を構築、jupyter notebookで使用する方法を紹介します。

OpenCVのインストール

ここではPythonのモジュール管理ソフトAnacondaを使用した例を紹介します。

Anacondaターミナルで次のコマンドを実行すれば、base環境にインストールできます。

conda install opencv

ただし、baseの環境には新規のライブラリをインストールすることは推奨されていません。

次のように新規の仮想環境を作成することをオススメします。

conda create -n 環境名
conda activate 環境名
conda install opencv

必要に応じて新規仮想環境にjupyter notebookやNumPyもインストールしておきましょう。

conda install numpy pandas notebook

jupyter notebookでOpenCVを使う

OpenCVをインストールした仮想環境でjupyter notebookを起動する方法を紹介します。

Anacondaのターミナルで次のコマンドを実行しましょう。

conda activate 環境名
conda jupyter notebook

もしくは、スタートメニュー ⇒ <Anaconda3(64-bit)> ⇒ <Jupyter Notebook(環境名)>をクリックしてもOKです。

白色部分の透明化(スクリプト紹介)

以下のスクリプトで、白色部分を透明化できます。

src.pngの白色部分が透明化されてdst.pngとして保存されます。

# OpenCVとNumPyをインポート
import cv2
import numpy as np
 
# 元画像の読み込み
path = "./figure_bgr.png"
src = cv2.imread(path)
 
# Point 1: 白色部分に対応するマスク画像を生成
mask = np.all(src[:,:,:] == [255, 255, 255], axis=-1)
 
# Point 2: 元画像をBGR形式からBGRA形式に変換
dst = cv2.cvtColor(src, cv2.COLOR_BGR2BGRA)
 
# Point3: マスク画像をもとに、白色部分を透明化
dst[mask,3] = 0
 
# png画像として出力
cv2.imwrite("dst.png", dst)

このスクリプトでは、次の3つがポイントです。

  • Point 1:白色部分に対応するマスク画像を生成
  • Point 2:元画像をBGR形式からBGRA形式に変換
  • Point 3:マスク画像をもとに、白色部分を透明化

次の3×3の画像を例に各ポイントを解説していきます。

Point 1:白色部分に対応するマスク画像を生成

画像の白色部分をTrue、それ以外をFalseとする真偽値の配列を作成します。

mask = np.all(src[:,:,:] == [255, 255, 255], axis=-1)

np.all()関数で、BGR全てが255(=白色)ならTrue、そうでなければFalseとなる配列を作ります。

このような特定の条件を満たす領域を抽出するための画像をマスク画像と呼びます。

Point 2:元画像をBGR形式からBGRA形式に変換

元の画像はBGRのデータしかないので、アルファチャンネルを追加します。

dst = cv2.cvtColor(src, cv2.COLOR_BGR2BGRA)

これでBGRA形式の画像になったため、透明度の設定ができるようになりました。

ここまでで下準備OKです。あろは白色部分を透明に書き換えるだけです。

Point 3:マスク画像をもとに、白色部分を透明化

画像の(x,y)の位置のピクセルのα値は、[x,y,3]に対応しています。

α値を0にすると透明になるので、マスク画像のTrueの場所(=白色)のα値を0にします。

dst[mask,3] = 0

これで白色の部分のα値が0になって、透明化されました。

このスクリプトを使えば次のように、白色を透明に変換できます。

おわりに

Web上に無料ソフトなどもありますが、自分でOpenCVを使えれば、複数ファイルの自動処理など、応用の幅が広がりますね。

これまで何冊かOpenCVの本や動画を見てきましたが、基礎から学ぶにはこちらの本がおススメです。

色の処理やフィルタ処理から始まってオブジェクト検出まで網羅的に解説しています。

PythonでのOpenCV初めての一冊にはピッタリかと思いますね。

【図解】Python NetworkXの使い方【サンプルコード有】 | ネットワーク分析・可視化

今回はpython強力なネットワーク分析ツールNetworkXを紹介します。

NetworkXを使用すると

  • ネットワーク分析
  • ネットワーク構造の可視化
  • 中心性や連結性などの解析

を行うことができます。

この記事は次のドキュメントや本を参考にしています。

興味が湧いた方はぜひこちらもチェックしてみてください!

 

ネットワーク分析の準備

基本用語の整理

まずは、ネットワーク分析に関する超基本用語を整理していきましょう。

次の4つの用語をおさえれば、簡単な可視化は可能です。

  • ネットワーク=グラフ, Graph
  • 頂点=ノード, node
  • 辺=エッジ, edge
  • 頂点の持つ辺の数=次数, degree

NetworkXのオブジェクトは英語名をもとに命名されているので、英語名を覚えた方が良いです。

環境構築

NetworkXは組み込みライブラリではないので、pipまたはcondaでインストールします。

ターミナルで次のコマンドを打ってインストールします。

pip install network
conda install network

環境構築は飛ばして、とりあえずネットワーク分析を試したい場合は、Google Colaboratoryを使用すれば、初めからインストールされているので設定不要です。

networkxのインポート

NetworkXnxという別名でインポートする慣例があるようです。

import networkx as nx

ネットワーク分析ではグラフの出力をすることもあるので、一緒にmaplotlibもインストールしておくと楽ですね。

%matplotlib inline 
# ↑jupter notebookで使用する場合のマジックコマンド
import matplotlib.pyplot as plt
import networkx as nx

ネットワーク分析・可視化の超基本形

ネットワークの可視化のためには、次の手順を踏みます。

  1. Graphオブジェクトの作成:G = nx.Graph()
  2. nodeの追加:G.add_nodes_from([node1, node2, node3,…])
  3. edgeの追加:G.add_edges_from([(node1, node2), (node2, node3), …])
  4. ネットワークの可視化:nx.draw(G, witlabels = True)

オブジェクト作成から、可視化までの基本形は次のようになります。

# Graphオブジェクトの作成
G = nx.Graph()
 
# nodeデータの追加
G.add_nodes_from(["A", "B", "C", "D", "E", "F"])
 
# edgeデータの追加
G.add_edges_from([("A", "B"), ("B", "C"), ("B", "F"),("C", "D"), ("C", "E"), ("C", "F"), ("B", "F")])
 
# ネットワークの可視化
nx.draw(G, with_labels = True)
plt.show()

これで、次のようなグラフが描けます。

以下では、このネットワークをもとに、

  • ノード、エッジ、次数の出力方法
  • ネットワーク図の装飾方法
  • ネットワークの超簡単な分析例

を紹介していきます。

基本的な特性値の出力

nx.info()関数で、Graphオブジェクトの情報をテキストで出力できます。

print(nx.info(G))
 
# Name: 
# Type: Graph
# Number of nodes: 6
# Number of edges: 6
# Average degree:   2.0000

Graphオブジェクトの情報をさっと確認したい場合には便利です。

細かい情報が欲しい場合には、以下で紹介するようなメソッドを使用します。

ノードの出力

ノードの基本出力メソッド:

  • ノードの総数:G.number_of_nodes()
  • ノードの要素:G.nodes()

出力例を見ていきます。

print("number of nodes:",G.number_of_nodes())
print("nodes:", G.nodes())
 
number of nodes: 6
nodes: ['A', 'B', 'C', 'D', 'E', 'F']

エッジの出力

エッジの基本出力メソッド:

  • エッジの総数:G.number_of_edges()
  • エッジの要素:G.edges()

出力例を見ていきます。

print("number of edges:",G.number_of_edges())
print("edges:", G.edges())
 
number of edges: 6
edges: [('A', 'B'), ('B', 'C'), ('B', 'F'), ('C', 'D'), ('C', 'E'), ('C', 'F')]

次数の出力

次数の基本出力メソッド:

  • 各ノードの次数:G.degrees()

出力例を見ていきます。

print("degrees:", G.degrees())
 
degrees: [('A', 1), ('B', 3), ('C', 4), ('D', 1), ('E', 1), ('F', 2)]

各ノードの次数が自動集計・出力されます。

ネットワーク図の見た目変更

nx.draw()メソッドにキーワード引数を設定することで、ネットワーク図の見た目を変更することができます。

ここでは、次の基本的なキーワード引数を紹介します。

  • ノード関連:
    • 色:node_color(デフォルト:'C0' 薄い青)
    • サイズ:node_size(デフォルト:300

 

  • エッジ関連:
    • 色:edge_color(デフォルト:'black' 黒)
    • 太さ:width(デフォルト:1

一括で設定(色、ノードサイズ、エッジの太さ)

キーワード引数としてシリアル値(リストでなく1つの値)を与えると、グラフ全体に適用されます。

ノードの色を"red"、エッジの色を"gray"、太さを500にしてみましょう。

nx.draw(G, with_labels=True, node_color = "red", edge_color = "gray", node_size = 500, width = 5)
plt.show()

ネットワーク図の見た目が一括で変更されていますね。

各要素で異なる設定を適用

リストで設定値を渡すことで、各ノード、エッジに異なる設定を適用できます。

各要素の順番に対応するように設定値を渡します。

次の例ではノードの各要素の色をcolorsというリストで渡しています。

colors = ["lightblue", "green", "red", "cyan", "magenta", "yellow"]
nx.draw(G, with_labels=True, node_color = colors)

同様に、node_sizeedge_colorwidthなどもリストで設定することが可能です。

ネットワークの特徴に合わせて見た目を設定すると見やすい図を作成できます

このようなネットワークの可視化については、次の本で詳しく解説されています。

この本や公式ドキュメントで、基本的な分析、可視化方法を学んでいくのがおススメです!

ネットワーク可視化例|次数に応じた配色・サイズ変更

最後に、各ノードの次数に応じて配色・サイズ変更する例を紹介します。

これまで、紹介してきた特性値の出力方法、ネットワーク図の見た目変更を組み合わせていきます。

次の図のように、

  • 各ノードの次数順の棒グラフ
  • 次数に応じたネットワーク図

を作成してみましょう。

このグラフは

  • 棒グラフとネットワークで各ノードの色が対応
  • ネットワーク図のノードのサイズが次数の数に比例

するように作成しています。

デフォルトのネットワーク図よりも視認性がだいぶ上がっています

きっと人に見せるときも、魅力的な図になりましたね!

次数に応じたネットワーク図の例

まずは、ノードの色付け、次数に応じたサイズ調整を行いましょう。

# ネットワーク全体の次数の平均値を計算
average_deg = sum(d for n, d in G.degree()) / G.number_of_nodes()
# ノードの次数に比例するようにサイズを設定
sizes = [300*deg/average_deg for node, deg in G.degree()]
print(sizes)
# [150.0, 450.0, 600.0, 150.0, 150.0, 300.0]
 
# グラフの出力
plt.figure(figsize = (10,5))
plt.subplot(121)
nx.draw(G, with_labels=True, node_color = colors, node_size = sizes, edge_color = "black")
plt.show() # ←棒グラフと並べて表示する場合は消します。

次数順の棒グラフの作成

次に各ノードの次数順の棒グラフを作成します。

# 次数の多い順番でnodeを並び替える
nodes_sorted_by_degree = sorted(G.degree(), key=lambda x: x[1], reverse=True)
print(nodes_sorted_by_degree)
# [('C', 4), ('B', 3), ('F', 2), ('A', 1), ('D', 1), ('E', 1)]
 
# 色のリストを次数順に並び替える
colors_dict = dict(zip(G.nodes(), colors))
colors_sorted = [colors_dict[node] for node, _ in nodes_sorted_by_degree]
print(colors_sorted)
# ['red', 'green', 'yellow', 'lightblue', 'cyan', 'magenta']
 
# グラフの出力
x, height = list(zip(*nodes_sorted_by_degree))
plt.subplot(122)
plt.xlabel("Number of degrees")
plt.ylabel("Name of node")
plt.barh(x, height, color = colors_sorted)
plt.show()

ネットワーク分析おススメの1冊!

pythonでネットワーク分析をしたい方には、こちらの本がおススメです。

実は私はネットワーク分析の基本どころか、NetworkXの存在すらしらなかったのですが…。

この本では

  • ネットワーク分析の流れや用語説明
  • NetworkXをサンプルコード付きで解説

されています。

私のような初学者でもすぐに簡単なネットワーク分析をできるようになりました

今回の記事では紹介しませんでしたが、本の中では

  • ネットワークの中心性を解析する方法
  • グループの分割・抽出方法

などに関しても解説されています。

ネットワーク分析の勉強にオススメな1冊でした!

おわりに

今回はネットワーク分析、NetworkXに関して紹介しました。

ネットワークを可視化すると、一気にデータが意味を持ちだすような印象を持ちます。

pythonの可視化にはmatplotlibを使用することが多いです。

今回も自然な流れでsubplotを使用していました。

matplotlibの簡単な使い方については、こちらの記事もご覧ください!

Twitter@YutaKaでは、ほぼ毎日pythonに関する情報を発信しています。

気楽にツイートしているので、気軽にフォローしてください!

Python turtle|組み込みモジュールturtleで桜を描こう!

pythonの標準ライブラリには、turtleという絵画用ライブラリがあります。

操作も簡単で、子供たちのプログラミング入門にも人気だそうです。

今回は、簡単な使用方法とその応用例としてturtleで桜を描く方法を紹介します。

turtleの基本的な使用方法

絵画を描くのに必要な最低限の機能をサンプルコード付きで紹介します。

詳しく知りたい方は、公式ドキュメントを参照してください。

絵画領域とタートルの作成

まずturtule.setup()関数で絵画領域を作成します。

その中に、タートルインスタンスturtle.Turtle()を作成します。

このタートルが、絵画領域内を走り回って、線を描きます。

import turtle
turtle.setup(width=300, height=300)  # 絵画領域の作成
my_turtle = turtle.Turtle()  # タートル

絵画領域の座標は(x, y)形式で、中心が(0, 0)です。

タートルを移動させる:forward(), setpos()

次の2つの移動方法を紹介します。

タートルの移動方法

forward(n):タートルが向いている方向に、nだけ前進

setpos(x, y):引数で指定した座標(x, y)に、タートルが移動

⇒移動する際に、タートルは線を描きます。

実際に移動してみます。

my_turtle.forward(100)  # 100前進
my_turtle.setpos(0, -100) #(0, -100)に移動

タートルが移動した際に、線を引きたくない場合には、penup()を実行します。

すると、次にpendown()が実行されるまで線が引かれなくなります。

my_turtle.penup() # 筆を上げる
my_turtle.forward(50)  # 100前進(筆が上がってるので線ひかない)
my_turtle.pendown() # 筆を下ろす
my_turtle.forward(-50)  # 100前進(筆が下がってるので線ひく)

タートルを回転させる:setheading()

setheading()では、指定した角度にタートルが回転します。

タートルの向き

右向き:setheading(0)

上向き:setheading(90)

左向き:setheading(180)

下向き:setheading(270)

回転と前進を、組み合わせると様々な線が引けます。

my_turtle.setheading(90)  # 上を向く
my_turtle.forward(100)  # 100前進

点を描く:dot()

dot()関数で、タートルがいる場所に●を描けます。

dot(n, "color")とすると、nでサイズを指定、"color"で色を指定できます。

my_turtle.dot(10, "red") # 赤丸を描く

これで線と●が自由に描けます。

あとはアイデアしだいで、いろいろなことができますよ!

応用turtleで桜を描く

タートルの基本機能を組む合わせて、桜を描いてみましょう。

ここで説明するスクリプトを実行すると、こんな桜が描けます。

サンプルコードのgistもありますので、ぜひ遊んでみてください!

hanasaka_python_simple.py · GitHub

桜を描く方法は次のサイトを参考に作成しました。

How to draw a beautiful tree 2.0 with Python - Programmer Sought

使用ライブラリ

turtlerandomのみです。

どちらも組み込みライブラリなので、importするだけです。

import turtle
import random

メインスクリプト

まずは、メインスクリプトを紹介します。

(クラスを作成すればもう少しすっきりします。今回は多くの人に楽しんでいただきたいので関数で作りました)

初期設定、種まき、木の成長、開花というフローになっています。

if __name__ == "__main__":
    # 絵画領域の準備
    turtle.setup(width=300, height=300)
 
    # タートルの用意
    my_turtle = turtle.Turtle()
    my_turtle.speed(0)  # タートルの移動速度の設定
    my_turtle.setheading(90)  # 上向きにする
 
    # 枝の短点を格納するリストを用意しておく
    bloom_point = []
 
    # 木が生える場所に種をまく
    seed(x=0, y=-150, my_turtle=my_turtle)
 
    # 木を成長させる
    tree(n=5, length=40, my_turtle=my_turtle, bloom_point=bloom_point)
 
    # 花を咲かせる
    bloom(my_turtle=my_turtle, bloom_point=bloom_point)
 
    # 終了後も絵画領域を表示させたままにする
    turtle.done()

次に各関数の中身を作成していきます。

種まき

オシャレに種まきseedと名付けましたが、木が生える場所にタートルを移動させるだけです。

def seed(x, y, my_turtle):
    # (x, y)にタートルを移動させる
    my_turtle.pu()  # 移動時、線を引かない
    my_turtle.setposition(x, y)

木を育てる

枝や幹を描く再起関数を作成します。

再起関数のフロー

幹から枝の先端まで、n回の分岐をするとする。

①幹を描いたら、先端でn1減らして、枝を描く。

n1減らして、枝を描く。

n0になったら、n=1に戻って分岐があればまた枝を描く。

③'分岐がなければ、n1増やして分岐があるか調べる。

このフローを再起関数で実現します。

def tree(n, length, my_turtle, bloom_point):
    # 幹または枝を描く
    my_turtle.pd()
    my_turtle.pensize(n)
    my_turtle.forward(length)

    # 描いている枝が、先端(n=0)でなければ、さらに分岐した枝を描く
    if n > 0:
        # 枝が生える分岐点の座標を記録
        branch_point = my_turtle.pos()

        # 分岐点から生える枝の数を2~4本でランダムに選ぶ
        branch_number = random.randint(2, 4)

        # 枝を1本ずつ
        for _ in range(branch_number):
            # 枝の角度、長さをランダムに決める
            branch_angle = random.uniform(-45, 45)
            branch_length = length * random.uniform(0.75, 0.9)

            # 枝の方向を向く
            my_turtle.right(branch_angle)
            # 再起関数で、もう一段細い枝を描く
            tree(n - 1, branch_length, my_turtle, bloom_point)
            # 枝の方向からもとの角度に戻る
            my_turtle.left(branch_angle)

            # 枝の分岐点に戻る
            my_turtle.pu()
            my_turtle.setpos(branch_point)

    # 描いている枝が、先端(n=0)であれば、座標を記録する
    else:
        # 枝の先端を記録
        bloom_point.append(my_turtle.pos())

ここではカウンターnを減らしながら、再起関数を呼ぶテクニックを利用しています。

再起関数のテクニック

・カウンターnを減らしながら実行

n>0nn-1にして、再起関数を内部で呼ぶ

・条件を満たしたら終了処理

n=0:先端の位置の記録

このテクニックを使用すれば再起関数を簡単に自作できます。

花が咲く

枝の先端にタートルを移動して、ピンクの円を描きます。

def bloom(my_turtle, bloom_point):
    my_turtle.pu()
    for position in bloom_point:
        # 花の場所に移動
        my_turtle.setpos(position)
        # 花が咲く
        my_turtle.dot(8, "pink")

あとはメインスクリプトを実行するだけです!

おわりに

今回はturtleを使用して、桜を描く方法を紹介しました。

工夫次第でいろいろなことができそうです!

ちなみに、クラスを作成したサンプルコードはこちらです。

hanasaka_python.py · GitHub

少しすっきりしてますね、桜を2本描くのも楽々です!

mpi4py:pythonで並列処理

pythonで並列処理をするにはmpi4pyというモジュールが便利のようです。

しかし、私の場合は初期設定でつまづいてしまいました。

とは言っても、実はモジュール以外にも必要なものがあるので、それをインストールすればいいだけの話でした!

今回はWindowsでmpi4pyを利用する方法をまとめます

mpi4pyについて、詳細を知りたい方は、公式ドキュメントもご覧ください。

MPI for Python — MPI for Python 3.0.3 documentation

MPIとは?

mpi4pyそのものが並列処理するのではなく、mpi4pyはpythonでMPIを使うためのモジュールです。

このMPIとは並列処理するための規格だそうです。

Message Passing Interface(メッセージ パッシング インターフェース、MPI)とは、並列コンピューティング利用するための標準化された規格である。実装自体を指すこともある。https://ja.wikipedia.org/wiki/Message_Passing_Interface

MPIは規格なので、どこかで入手しなければいけないようです...無料でないのかな...と思ったら?

Windows 環境では、MSMPIが使える!

WindowsではMicrosoft MPIというものを無料で利用できます!!

MSMPIと略されることが多いみたいです。

MSMPIのインストール

MicrosoftのHPからダウンロードして、インストールします。

次の二つをインストールする必要があります。

  • msmpisdk.msi
  • msmpisetup.exe

mpiexecへのパスを通す

並列計算の場合はpython.exeではなく、mpiexec.exe を使用します。そのため、このmpiexec.exeへのPATHを通しておく必要があります。

デフォルトでインストールした場合は、C:\Program Files\Microsoft MPI\Binに保存されます。

コマンドプロンプトでPATHを確認しましょう!次のコマンドで確認できます。
echo %path:;=&echo.%

f:id:YutaKa:20191129125612p:plain
私の場合は自動でPATHも通っていました(もしかして、msiでインストールして、exeでPATH通してるのかな?順番が大事??)。通ってなかったらPATHを通しましょう。

mpi4pyの入手

mpi4pyは、defaultチャンネルや conda-forgeにはなく、anacondaチャンネルにあります。

次のコマンドでmpi4pyを使うためのmpi_envという仮想環境を作ってみます。
conda create --name mpi_env mpi4py -c anaconda 

f:id:YutaKa:20191129130053p:plain

これでMPIの準備とmpi4pyの準備が完了です!

テストランしてみよう

今作った仮想環境でテストラン用のスクリプトを作ります。私の場合は、condaで作った環境をpycharmで使用しています。

yutaka01.hatenablog.com

お試し用にmpi_test.pyというスクリプトを作成してみます。

from mpi4py import MPI

comm = MPI.COMM_WORLD # 並列処理開始です!

size = comm.Get_size() # 並列処理に使用できるプロセッサ数
rank = comm.Get_rank() # 各プロセッサのIDのようなもの

print("Hello world {0} / {1}".format(rank, size))
並列処理できれば、各プロセッサがHello Worldを出力するはずです!!

python.exeで実施

普通にターミナル(pycharm画面の下の方にあります)でランすると...
python mpi_test.py

f:id:YutaKa:20191130120849p:plain

一個しか出てこない!!失敗!

mpiexecで実施

並列処理にはmpiexec.exeで、python.exeを実行する必要があります!
例えば2つのプロセッサを使うときは次のようにしてプロンプトに入力します。
mpiexec -n 2 python mpi_test.py

f:id:YutaKa:20191130120950p:plain

無事に2つのプロセッサからHello Worldが返ってきました
おつかれさまです(⌒∇⌒)

まとめ

Pythonで並列処理するには、mpi4pyを使用するのが便利です!
そのためにはMPIという規格が必要ですが、windows であればMSMPIという無料のMPIが使用できます!
自分が使いたい外部モジュールがmpi4pyを使用している場合にも、MPIは必要になるので、記憶にとどめておいてください!
この記事を読まれた方は、数値計算・科学積算系のことをされている方が多いのではないでしょうか?
数値計算関係のpythonの書籍では、次のものがおススメです。 
科学技術計算のためのPython入門 ――開発基礎、必須ライブラリ、高速化

科学技術計算のためのPython入門 ――開発基礎、必須ライブラリ、高速化

  • 作者:中久喜 健司
  • 発売日: 2016/09/22
  • メディア: 単行本(ソフトカバー)