これまでのあらすじ:
2016年3月、フェルト生地を手で裁断している際にレーザーカッターがあれば複雑なカットが容易にできるなあと思って、安価になってきたレーザーカッターを購入しようと思ったのがきっかけ。調べていくうちに、合板も切れたほうがいいと思うようになって、CNCルーター(CNCミリング)についても考えるようになった。
Arduinoは以前から使っており、CNCシールドがあると気付いて自作も可能と思うようになった。当初はShapeOkoやX-CARVEを参考にMakerSlide、OpenRail、V-Wheel、2GTタイミングベルトなどで5万円くらいで自作しようと思っていた。AliExpressでも部品が安く買えることが分かって、しばらくは部品探し。探せば探すほど安くて本格的な部品も見つかってくるので、そんなにケチらなくてもいいのではないかと徐々にスペックアップ。最終的には剛性や精度のことも考えてボールスクリューやリニアスライドを使うことになり、予想以上に重厚な3軸CNCマシンをつくることに(約7万円)。
構想から約5週間(制作約3週間)でルーターとレーザーともに使えるようになり、現在はgrbl1.1+Arduino CNCシールドV3.5+bCNCを使用中(Macで)。余っていたBluetoothモジュールをつけてワイヤレス化。bCNCのPendant機能でスマホやタブレット上のブラウザからもワイヤレス操作可能。


CNCマシン全般について:
国内レーザー加工機と中国製レーザー加工機の比較
中国製レーザーダイオードについて
CNCミリングマシンとCNCルーターマシンいろいろ
その他:
利用例や付加機能など:
CNCルーター関係:

*CNCマシンの制作記録は2016/04/10〜の投稿に書いてあります。

2018年4月19日木曜日

Jupyter Notebook/JupyterLab: matplotlib GIFアニメーション 作り方+読込み+表示方法

前回に引き続き、Jupyter NotebookとJupyterLabでのmatplotlibをつかったアニメーションについてのメモ。matplotlibは便利なのだけれども、個人的には使いづらく(覚えにくい)、特にアニメーションではかなりハマったので書いておきます。

環境:
Ubuntu 16.10
Python3.5
Jupyter Notebook 5.0.0
JupyterLab 0.32.0
matplotlib 2.2.2


まず、Jupyter NotebookやJupyterLab上に表示する際、
・%matplotlib inline (主に静止画)
・%matplotlib nbagg (動画、インタラクティブ)
この二種類のbackendsを用いるのですが、基本的にJupyterLabだと「nbagg」のほうはダメみたい。

次に、グラフをアニメーション化するには二つの方法があるようで、
・ArtistAnimation (比較的簡単)
・FuncAnimation (やや複雑)
パラメータが少なければどちらもそう難しくはないのですが、場合によっては表示されない場合もあります。表示されなくてもGIFアニメーションに保存はできることもあります。

これはつくったGIFアニメ。比較的簡単につくることができるけれども、JupyterLabに表示させるのが難しい。

表示方法(3種類):
そして、Jupyter上で表示する方法としては3つあり、

・nbaggを用いたインタラクティブウィンドウ(JupyterLabではエラー)
・inlineのままJavascript HTMLで出力する方法(JupyterLabではエラー)
・inlineのままHTML5 Videoとして出力する方法(エラーなし)

バックエンドをinlineのままJavascript HTMLやHTML5 Videoを使うためには、

from IPython.display import HTML


が必要となります。

以下がそれぞれの見た目です(キャプチャ画像なのでボタンを押しても動きません)。

バックエンド:%matplotlib nbagg
表示:animation.ArtistAnimation
JupyterLabでは表示不可


バックエンド:%matplotlib inline
変換表示:JavascriptHTML
JupyterLabでは表示不可
この中では一番多機能、逆再生・往復再生・スピード調整など可能

バックエンド:%matplotlib inline
変換表示:HTML5 Video
Jupyter Notebook、JupyterLabともに表示可能
動画ダウンロード・フルスクリーン表示可能


Jupyter Notebookではどれも大丈夫でしたが、JupterLabではJavascriptのエラーなのか最初の二つはダメそうです。HTML5 Video出力だと大丈夫だったので、これがおすすめかもしれません。
バグなのか、設定方法が悪いのか、インストールが不十分なのかわかりにくく結構手間取ってしまいました。


今回試してみたこと:
・グラフをアニメーション化して再生、GIFアニメーション保存
・つくったGIFアニメーションを読み取って再生する方法
・Jupyter上にマークダウンとしてGIFを表示する方法

下準備(インストール:このサイト参照):
Nodejs
npm
ipympl
jupyter-widgets/jupyterlab-manager
(It requires matplotlib 2.0 or and ipywidgets 7.0 more recent.)



グラフのアニメーション化・再生・GIFアニメーション保存:
「ArtistAnimationを使った場合」

%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
from IPython.display import HTML

fig = plt.figure()
x = np.linspace(-5,5,100)
y = np.sin(x)

ims = [] # 動画要素を格納するリスト

for i in range(len(x)):
    ln = plt.plot(x,y, 'b--')     # 動かない線
    pt = plt.plot(x[i],y[i],'ro') # 移動する点
    ims.append(ln + pt)

ani = animation.ArtistAnimation(fig,ims,interval=50) # アニメ関数

ani.save("test.gif", writer = "imagemagick") # GIF保存

plt.close() #余計なウィンドウがでた場合消す

HTML(ani.to_html5_video()) # HTML5 Videoで表示
# HTML(ani.to_jshtml())    # Javascript HTMLで表示


アニメーション化するには、animation.ArtistAnimation()に最低でもfigとimsの二つの引数を渡し、imsに動画になる要素としてのplt.plot()を必要なだけ+を使って入れていくだけ。
その下のani.save()でGIFとして保存。Ubuntuの場合はwriterとしてimagemagickを指定したほうがいいらしい。
plt.close()については、バックエンドで%matplot inlineがはたらいているためか、HTML5 Videoのウィンドウとは別にもうひとつplt.figure()の空ウィンドウが出てくることがあって、それを消しています。
Jupyter Notebookなら、HTML(ani.to_jshtml)に切り替えても表示できました。nbaggを使わずinlineで済むのでお手軽です。ただし、HTMLをインポートしておく必要があります。
%matplotlib inlineは切り替えなければデフォルトになっているようなので、途中でnbaggなどに変えなければ記入する必要はありません。


「FuncAnimationを使った場合」

%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
from IPython.display import HTML

x = np.linspace(-5,5,100)
y = np.sin(x)

fig = plt.figure()
plt.axis([-5,5,-2,2])      # 座標範囲:[xmin,xmax,ymin,ymax]
b, = plt.plot([],[],'b--') # 固定描写(青破線)
t, = plt.plot([],[],'r-')  # 移動描写(赤丸)

# plt.axis('off') # 枠線なしの場合

def update(i):
    b.set_data(x,y)           # 固定描写(青破線)
    t.set_data(x[i], y[i])    # 現在の移動座標のみ表示(点描の場合)
    #t.set_data(x[:i], y[:i]) # 過去の軌跡座標も表示(線描の場合)

ani = animation.FuncAnimation(fig, update, interval=50) # アニメ関数

ani.save("test.gif", writer = "imagemagick") # GIF保存

plt.close()

HTML(ani.to_html5_video())   # HTML5 Videoで表示
# HTML(ani.to_jshtml())      # Javascript HTMLで表示


こちらの方法だとupdate(i)関数を作って、フレーム数となる引数iを入れてFuncAnimation()に渡すことになります。他の方法でも可能なのかもしれませんが、サンプルなどではline2Dオブジェクト用の変数(t, : 変数の後ろにコンマ付き)を用意し、set_data()で更新していくようです。やや複雑なことが可能なのかもしれません。subplotを追加するサンプルが多いですが、plt.plotだけを使って書いてみました。


バックエンド(inline/nbagg)切替方法・確認方法:
以下のコマンドで現在使用されているバックエンドを切替・確認できます。


%matplotlib inline
# %matplotlib nbagg

import matplotlib
matplotlib.get_backend()


この状態だと、inlineが使用されているので以下が出力されます。


'module://ipykernel.pylab.backend_inline'


通常の静止画グラフやHTML5 Video、JavascriptHTMLを使うならばinlineに設定。
また、コメントアウトでnbaggに切り替えれば、

'nbAgg'


が出力されて、nbaggがバックエンドとして使用されていることがわかります。ただし、JupyterLabではJavascriptエラーがでるかもしれません。


GIFアニメの読込と再生:
先ほどの方法でGIFアニメをつくることができますが、それを再生する方法についてです。
最初はそのままGIF画像を読み込めば表示できると思っていましたが、なかなかうまくいきませんでした。静止画であればすぐに表示できますが、動画として連続的に表示してくれずかなりハマりました。

まず、PILを使って以下のようなGIFファイルの内容を調べます。


from PIL import Image

img = Image.open("test.gif")

print("info: ",img.info)
print("animated: ",img.is_animated)
print("n_frames: ",img.n_frames)


そうすると、以下のような情報が出力されます。


info:  {'version': b'GIF89a', 'duration': 50, 'loop': 0, 'background': 0, 'extension': (b'NETSCAPE2.0', 803)}
animated:  True
n_frames:  100

このGIFファイルの場合はanimatedされているというのがわかります。またフレーム数が100あることもわかります。基本的にはこの二つの情報がわかれば大体大丈夫だと思います。
そのままこの二つの変数を使えば、異なるGIFファイルも読み込むことができると思います。


import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
from IPython.display import HTML
from PIL import Image

img = Image.open(filepath+"-test.gif") # PIL Imageで読込み

# GIFの情報を調べる(今回はフレーム数だけ)
# print("info: ",img.info)
# print("animated: ",img.is_animated)
print("n_frames: ",img.n_frames)       # フレーム数を取得

fig = plt.figure()

# plt.axis('off') # 枠線なしの場合

ims = []    # 各フレームを格納するリスト

for frame in range(0,img.n_frames):  # フレーム数だけループ処理
    img.seek(frame)                  # 順番に各フレーム画像を探し出す
    im = plt.imshow(img)
    ims.append([im])

ani = animation.ArtistAnimation(fig,ims,interval=50)

plt.close()

HTML(ani.to_html5_video())
# HTML(ani.to_jshtml())


まず、内包されているフレーム数を調べるために、PIL Imageをインポートしておきます。img=Image.Open()したあとに、img.n_framesでフレーム数がわかります。
あとはそのフレーム数だけループ処理をし、ひとつずつリストに格納していきますが、img.seek()という関数を使うことで内包されている何番目の画像を取り出すか指示できます。
img.seek(0)なら最初の画像、img.seek(1)ならその次の画像というような感じで次のplt.imshow()に入れていきます。GIFの場合はこのimg.seek()を使うといいようです。
もし連番のPNG画像を複数扱うならば、img.seek()は使わずに、ファイル名の番号を手がかりに読込みと表示をさせればいいことになります。

順番にひとつずつ取り出してはimg.show()やplt.imshow()で表示させてもいいと思ったのですが、そうするとJupyter上では次々と複数の静止画が出てきて動画として見ることができませんでした。出しては消すという方法ももあるのかもしれませんが、今回はArtistAnimation()に取り込んで動画として表示させることにしました。


Jupyter上にマークダウンでGIFアニメを表示する:
先ほどのやり方は、GIFアニメを一枚ずつ取り出して、何らかの加工をするときには使えるテクニックかもしれませんが、ただ出来栄えを確認したり表示するだけなら、マークダウンでJupyter上のセルに表示させればいいと思います。


### Animated GIF
<div class="pull-left">
![Animated GIF](test.gif)
<div>

Jupyter上のセルをマークダウンに切り替えてこんな感じで記入すれば、普通にGIFアニメとして表示されるはずです。この場合は普通の静止画と同じ読込み方です。


2018年4月17日火曜日

JupyterLabを使ってみた(便利そうだけど、いまいち)

最近は、Jupyter Notebookを使っていますが、それと似たようなものでJupyterLabというのがAnaconda Navigatorに前からあったので試しにつかってみました。

Jupyter Notebookと同様にブラウザ上で使うことができるので便利。
さらにツリービュー、ターミナル、エディタもあり、画面分割可能でだいたい一通りのことができます。

Anaconda Navigatorからすぐにインストール(不要ならアンインストール)できるので試してみるにはよさそう。
かなりJupyter Notebookからは進化しているのですが、まだベータ版のようです。

右クリックでコピペできない:
ということでしばらく使っていると、やはりベータ版なのか多少不便な点が。
まず、マウス右クリックでコピペがメニューに出てこない。右クリックすると、以下のようなメニュー。

セル単位でのコピペは可能。しかし単語や行だけのコピペはできないために、仕方なくキーボードでCtrl+C、Ctrl+Vを入力するしかない。なんとメニューバーにすらない。

もうひとつとして、せっかくターミナルも同一画面上で使用できるのにもかかわらず、同様に右クリックだけではコピペできない。そのかわり、シフトキーを押しながらの右クリックならメニューが出てくる(以下)。

つい癖で右クリックしてみたものの、コピペできないということが少しストレスを感じてしまいます。改良されないのでしょうか?


%matplotlib nbaggが使えない:
Jupyter notebookではplt.plot()で表示するするとき、%matplotlib inlineを使いますが、アニメーションなどを表示するには、%matplotlib nbaggを使っています。しかしnotebookのほうでは使えるけれども、JupyterLabのほうだと、Javascriptエラーがでてしまいます。

JavaScript output is disabled in JupyterLab

しかし、このページにいくつか対処策があるようです。

conda install notebook jupyterlab # for updating jupyter notebook and lab
pip install ipympl
jupyter labextension install @jupyter-widgets/jupyterlab-manager jupyter-matplotlib

事前にnodejsとnpmをインストールしておき、notebookとjupyterlabをアップデート、さらにipympl、jupyter-matplotlibをインストールとのこと。
しかし、それでもなぜかエラーがでてしまいます。このページでも話されていることなのですが、まだダメっぽい。

また、%matplotlib nbaggを使っても、

こんな感じのエラーがでてしまいます。%matplotlib ipymplを使うともっとひどいエラーがでてしまい、jupyter-matplotlibがダメみたい。何回かインストールし直してみましたが改善されないので、今回は保留。

ということから、結構使い勝手はよくなっているJupyterLabなのですが惜しい。ベータ版なので仕方ないのかもしれませんが、しばらく待ってみることにします。
そもそも、Jupyter Notebookなら特に問題ないので、今まで通りJupyter Notebookでいいかと。

しかし、その後、jupyter-matplotlibのサイトをみると、

It requires matplotlib 2.0 or and ipywidgets 7.0 more recent.

と書いてあることからチェックしてみると、ipywidgetsのバージョンが低いことが判明。さっそくアップデートしてみました。
すると、いままで%matplotlib nbaggではだめだったgifアニメーション制作が可能になりました。
そして、上のようにバックエンドを確認してみたところ、いままではnbAggと出力されていたのが、'module://ipykernel.pylab.backend_inline'になっていました。少しだけ進展したのですが、あいかわらずアニメーション自体は表示されず、もう少しというところ。しばらくすれば、また進展あるかも。
要は、このようなアニメーションをJupyterLab上で表示させたいのですが、一コマごとに出力したpngファイルを順番に表示することができずにいるということです。このアニメーションはpngを束ねてgifアニメにしたものですが、それも表示できません。バージョンアップによって制作はできるようになったので、よかったのですが惜しい。もちろんJupyter Notebook上では表示も制作も問題ないというわけです。

その後もう少しやってみると、どうやらJupyterLabではmatplot.animationを使う場合、アニメーション出力はHTML(ani.to_html5_video())を使うと大丈夫でした。もうひとつHTML(ani.to_jshtml())というのもあるのですが、こちらはダメみたい。Jupyter Notebookではどちらとも大丈夫ですが、JupyterLabの場合はHTML(ani.to_html5_video())を使ったほうがよさそうです。

追記:
その後、GIFアニメーションの作成+読込み+再生について実験してみました

2018年4月9日月曜日

Tensorflow 1.7へバージョンアップ

Tensorflowは少し前に1.6へバージョンアップしていたにもかかわらず、pytorchを使っていたため1.5のままでした。しかし1.6のあとすぐに1.7へバージョンアップしており、eager executionが改良された模様。



TensorflowはさすがGoogleだけあって開発スピードがはやいのか、内容に追いついていくのが大変。
Tensorflowといえば、

tf.placeholder()
tf.Variable()
tf.Session()

でコーディングしていくイメージでしたが、より使いやすくするために

tflearn : easy to learn, high level API
slim : a lightweight library for defining, training and evaluating models
estimator : a high-level TensorFlow API that simplifies ML programming
keras : a higher API wrapper
eager : define by run
lite : mobile, RPi

などが次々と導入されたため、どれがいいのかわかりにくくなってきたという感じ。
kerasが使えるようになってからは、シンプルなコーディングが可能になったけれども、pytorchのようなdefine by runタイプが便利になってきたこともあって、Tensorflowもeagerを導入してdefine by runも普通に使えるようになった感じ。

なんでもありとなってきたTensorflowという感じで、やはり機械学習フレームワークとしてはTensorflowがなんだかんだいって便利なのかもしれません。
ということで、使い勝手が改良されたTensorflowも再度使おうと、1.5から一気に1.7へバージョンアップしてみました。

GPUを使用しているので、

pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.7.0-cp35-cp35m-linux_x86_64.whl

のpipコマンドでAnaconda仮想環境内にインストールしてあったtensorflow-gpu-1.5.0をアップグレード。
eager executionが便利そうなので、少し慣れておこうかと。

最近は、ベイズ推定などの確率的プログラミングに興味があって、

GPy
Pyro
Edward

などを勉強していまずがTensorflowにも、

Tensorflow Probability

というライブラリができたようで、Tensorflowだけであらゆることが可能となってきた感じ。



2018年2月26日月曜日

Anaconda NavigatorのVSCODE

Anaconda NavigatorにVSCODEが追加されたようなのでアップデートしてみました。
環境は、Ubuntu16.10です。


アップデートしてみると、たしかにVSCODE(右下)に追加されています。
選択した仮想環境内にあるVSCODEの「install」をクリックすれば、すぐにインストールされるようです。もうすでにPythonの環境に適応した状態になっているようなので、余計な設定などしなくてもいいようです。
もともとAnaconda Navigatorにはspyderというエディタも入っているのですが、おそらくVSCODEのほうが使いやすいかと。

しかし、普段はAtomエディタを使っているので(以前いろいろ設定したので)、VSCODEはたぶん使用しないとは思いますが、徐々に便利になっていることは確かです。やはりPythonを使うならばAnacondaを導入するのがおすすめです。

2018年2月19日月曜日

小型直動サーボ:GS1502とミニアクチュエータ


AliExpress.com Product - 2pcs/lot 1.5 g 1.5g servo micro digital servo loading two linear servo1107円(2個/送料無料)
ラジコン飛行機用のサーボらしいけれども直動というのがめずらしい。ストロークは以下の写真をみると10mm程度でしょうか。


以前、CD-ROMヘッド用のミニアクチュエータをAliExpressで見つけましたが(以下)、こちらはステッピングモーターを使っているので脱調しなければ精度・分解能はありそう。
AliExpress.com Product - circle 2 Phase 4 wire Mini screw rod stepper motor for camera Linear motor sliding table lead screw stepper motor
それぞれ、285円/296円/307円(送料無料)、比較的安い。
ストロークは、19mm/29mm/40mmのようです。

ミニCNCやミニロボットアームなど作れそうです。
いちおう気になったのでメモ。

人気の投稿