福野泰介の一日一創 - create every day

2019年度の人気プログラミング言語ナンバーワンのPythonGitHubのアクティブでも不動の1位、PC上のPythonを使ってIchigoJamをコントロールして、かんたんIoTを実現してみましょう!

ネットにつながっているPC、Pythonを使えば世界中のさまざまなデータをAPI経由、スクライピングなどで、取得し放題。
Python2年生 スクレイピングのしくみ 体験してわかる!会話でまなべる! | 森 巧尚 | コンピュータ・IT | Kindleストア | Amazon」(まもなく登場!1年生はこちら

でも、PCではデバイスやセンサーなどを直接制御はできません。
そこで、それら電子部品の制御が得意なIchigoJamとUSBシリアルでつないでいいとこどり。

IchigoJamにUSBシリアルをつなぐか、IchigoKamuyを使って、PCに接続したら、Python用シリアル通信ライブラリ「pySerial」をセットアップ

pip3 install pyserial

USBシリアルのポート(port)を /dev/tty.〜 または COM3 などで指定し、LEDをつけるプログラムはこちら(シリアルを閉じる前に0.1秒待ちをいれてます)

import serial import time port = '/dev/tty.SLAB_USBtoUART' ser = serial.Serial(port, 115200) ser.write(b'LED1\n') time.sleep(0.1) ser.close()

好きなコマンドをIchigoJamへ送って、結果を1行表示するPythonプログラムをつくって

import serial import time import sys port = '/dev/tty.SLAB_USBtoUART' ser = serial.Serial(port, 115200) ser.write(sys.argv[1].encode('utf-8')) ser.write(b'\x0a') print(ser.readline().decode('utf-8')) time.sleep(0.1) ser.close()

IchigoJamコマンドをPCのコンソールから自由自在に送信可能!(例、LEDオフ、出力ポート制御、アナログ入力、サーボ制御)

python3 command.py 'LED0' python3 command.py 'OUT1,1:WAIT60:OUT1,0' python3 command.py '?ANA(2)' python3 command.py 'PWM2,100'

IchigoJam 1.4βファームウェアを使えば、マイコン内蔵フルカラーLEDのまとめて制御もこのように簡単!(リファレンス

python3 command.py 'LET[0],10,0,0:WS.LED1,50'


ネットで取得したデータに合わせて派手にお知らせできますね!
その他、いろいろサンプルプログラム in Python はこちら
IchigoJam/IchigoJam-control-by-python: IchigoJam control by Python

links
- Rubyで操るフルカラーLED50コ、USBシリアル x IchigoJam x Ruby編!
- IchigoJamでパソコンとUSBシリアル通信。Node.jsを使うとキーボードとモニタいらず – しずかなかずし

データで遊ぼう!

山口県工業技術センターにて開催「衛星データ解析技術研究会」にてオープンデータ特集。
オープンデータと宇宙データを組み合わせると、ますます楽しく遊べます。

自治体5つ星オープンデータ化を支援するodpなど、5つ星オープンデータの広まりを心待ちにしつつも、いますぐプログラミングして遊べる楽しいこと、はじめましょう!


Tellusで使える2010年3月〜2018年7月末までの降雨量データ、緯度経度共に0.1度の精度で降雨量が分かります。これを使って宇部市、常磐公園や宇部高専あたりの晴天率を調べてみました。

2018年6月の晴天率は、60%とでました。
Tellus OSでもチェックできますが、プログラムにするといろんな場所を自動的にチェックできて便利です。

こちらが計算するのに使った、Jupyter Notebookで動かすPythonプログラム。

TOKEN = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" import os, json, requests, math from skimage import io from io import BytesIO import calendar import matplotlib.pyplot as plt %matplotlib inline def get_image_GSMaP(date, xtile, ytile): sname = "GSMaP" zoom = 5 url = "https://gisapi.tellusxdp.com/{}/{}/{}/{}/{}.png".format(sname, date, zoom, xtile, ytile) print(url) headers = { "content-type": "application/json", "Authorization": "Bearer " + TOKEN } r = requests.get(url, headers=headers) return io.imread(BytesIO(r.content)) def ll2tile(lat, lng, z): w = math.pow(2, z) / 2 yrad = math.log(math.tan(math.pi * (90 + lat) / 360)) return [ (lng / 180 + 1) * w, (1 - yrad / math.pi) * w ] def get_pixel_GSMaP(date, lat, lng): tile = ll2tile(lat, lng, 5) img = get_image_GSMaP(date, math.floor(tile[0]), math.floor(tile[1])) return img[math.floor(tile[0] * 256 % 256)][math.floor(tile[1] * 256 % 256)] def calc_fine_ratio(y, m, lat, lng): cnt = 0 _, ndays = calendar.monthrange(y, m) for d in range(1, ndays + 1): date = "{:0=4}-{:0=2}-{:0=2}".format(y, m, d) rgba = get_pixel_GSMaP(date, lat, lng) #n = (rgba[0] << 24) | (rgba[1] << 16) | (rgba[2] << 8) | rgba[3] n = rgba[3] print(date, n) if n < 255: cnt = cnt + 1 return cnt / ndays calc_fine_ratio(2018, 6, 33.931245,131.277600)

緯度経度からタイル座標への返還は、こちらJavaScriptのプログラムを参考にしています。


PCN山口代表のコヤマさんにも会えました!宇部高専生によるPCN宇部との連携、はじまります!


さくらインターネット、小笠原さん、牟田さんとも楽しいパネルディスカッション。


講演資料オープンデータ「オープンデータと宇宙データで地域活性化(PDF)


日本の衛星、だいち2号(ALOS-2)の1/3スケール模型。この子が宇宙からデータを届けてくれているんですね!
1/1スケール模型、Oculus QuestでぜひVR表示させたいところ!3Dオープンデータ探します。


山口名物、瓦そば!
瓦そばオープンデータがあったら、衛星データと組み合わせて、どんなアプリを作りますか?
こどももおとなも、レッツ、プログラミング!

宇宙データプラットフォームを使った分析はじめ、続いては、お気に入りデバイス Oculus Questと組み合わせます。
2.5mの分解能で宇宙から標高を計測する、ALOS-PRISM。Tellusの開発環境、Jupyther Notebookを使って富士山付近のデータをエクスポートして、VR表示しました。


VR fujisan
マイクラでリアルなマップを再現したい夢、データとプログラミングを使えば簡単に叶います!

作り方
1. Tellusに、Jupyther Notebook か Jupyter Lab を利用申請。
2. 富士山の位置のメッシュを調べる。(タイル座標確認ツール
3. Jupyter Notebook上、Pythonでプログラムをかく

TOKEN = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" import os, json, requests, math from skimage import io from io import BytesIO import matplotlib.pyplot as plt %matplotlib inline def get_image(zoom, xtile, ytile, opacity=1, r=3, g=2, b=1, rdepth=1, gdepth=1, bdepth=1, preset=None): sname = "aw3d30" url = "https://gisapi.tellusxdp.com/{}/{}/{}/{}.png?opacity={}&r={}&g={}&b={}&rdepth={}&gdepth={}&bdepth={}".format(sname, zoom, xtile, ytile, opacity, r, g, b, rdepth, gdepth, bdepth) if preset is not None: url += '&preset='+preset headers = { "content-type": "application/json", "Authorization": "Bearer " + TOKEN } r = requests.get(url, headers=headers) return io.imread(BytesIO(r.content)) img = get_image(10,906,404) io.imshow(img)

富士山の標高データが画像で表示されます。
4. RGB値が最高になっているようなので、最大値を求めてみる(きっともっとシンプルに書けます)

max = 0 for d in img: n = (d[0] << 16) | (d[1] << 8) | d[2] if n > max: max = n print(max)

結果

12766

富士山の高さは3766mなので、9000ずれた1m単位だと推定。 5. 試しにテキストで表示してみる

for y in range(256): for x in range(256): d = img[x,y] n = (d[0] << 16) | (d[1] << 8) | d[2] n -= 9000 n /= 4000 n = math.floor(n) print(n,end='') print()


それっぽい。
6. JavaScript用に配列データとして出力

h = [] for y in range(256): for x in range(256): d = img[x,y] n = (d[0] << 16) | (d[1] << 8) | d[2] n -= 9000 h.append(n) print(h)

このデータを、fujisan-data.js として保存して、JavaScriptでWebVRを使ったVRアプリをつくって、できあがり!

<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>VR fujisan - data by Tellus</title> <script src="https://aframe.io/releases/0.9.1/aframe.min.js"></script> <script src="https://fukuno.jig.jp/app/webvr/fujisan-data.js"></script> </head> <body> <script>"use strict" window.onload = function() { var scene = document.querySelector('a-scene') const r = 1 const rw = 4 // sampling rw * rw const bw = 256 // org data sampling w and h const w = bw / rw let map = [] for (let i = 0; i < w * w; i++) { const x = i % w const y = (i / w) >> 0 const p = x * rw + y * rw * bw const n = HEIGHT[p] map[i] = n } for (let i = 0; i < map.length; i++) { const x = i % w const y = (i / w) >> 0 const h = map[i] * 0.0005 let box = document.createElement('a-box') box.setAttribute('position', { x: (x - w / 2) * r, y: h / 2 * r - 7, z: (y - w / 2) * r }) box.setAttribute('depth', r) box.setAttribute('width', r) box.setAttribute('height', r * h) scene.appendChild(box) } } </script> <a-scene id="scene"> <a-sky color="#000000"></a-sky> <a-light color="blue" position="1 0.1 0.5"></a-light> <a-light color="cyan" position="0.1 4 2"></a-light> </a-scene> </body> </html>

縮尺は適当なのでリアルな富士山ではないですが、これで怪獣や巨人になった気分で富士山付近を歩けます。
VR x Tellus、楽しいですよ!

links
- VRではじめる現代HTML入門 - Oculus Quest x 福井高専生
- 50行で作るVRマイクラ風 / boxcraft for Oculus Quest with A-Frame
- モバイル時代こそバス! つつじバスロケVRビジュアライズ - リアルタイムオープンデータ x Oculus Quest
- 異次元の分かりやすさ、触って学ぶVR数学、ベジェ曲線編 on Oculus Quest

600万円、これは世界一高い参議院選挙立候補に必要な供託金(市議選は30万円)。
第25回参議院選挙の投票日は7/21。 前回投票日の2016年7月10日の投票所と人の流れをTellusで見てみました。


Tellus ver 1.1 によって追加された、位置情報データ「Profile Passport」を使って、投票日7/10の10時時点(日本時間はUTC+9時間)を品川区の5つ星オープンデータ、投票所と組み合わせて表示した図。 もう一歩分解能がほしいところですが、投票所への人の流れがわかるかも?通常の日曜日との比較なども可能です。


鯖江市の選挙ポスター掲示場、オープンデータと宇宙データ、だいち(ALOS)のセンサーAVRIR-2による植物活性度を重ねたもの。鯖江市の東側、自然豊かな場所にあることが一目瞭然。


Tellusを使った分析は、Jupyter Notebookや、後継サービスJupyter Lab上のPythonで行います。
5つ星オープンデータを集約する opendata.cc のAPI、SPARQLを呼び出し、GeoJSONにしてpostするとTellus上の「取り込みマップ」として表示できます。

API_TOKEN = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # Tellus マイページ、APIアクセス設定で生成したトークン import json, requests, urllib.parse URL = "https://api.tellusxdp.com/v1/geojson-files" def get(id = ""): return requests.get(URL + "/" + id , headers = { "Authorization": "Bearer " + API_TOKEN }).json() def post(data): headers = { "Authorization": "Bearer " + API_TOKEN, "Content-Type": "application/json" } return requests.post(URL, headers = headers, json = data).json() def delete(id): return requests.delete(URL + "/" + id, headers = { "Authorization": "Bearer " + API_TOKEN }).json() SPARQL_ENDPOINT = "https://sparql.opendata.cc/data/sparql?output=json&query=" def sparql(query): url = SPARQL_ENDPOINT + urllib.parse.quote(query) return requests.get(url).json() def toGeoJSON(res): fs = [] for d in res["results"]["bindings"]: f = { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ d["lng"]["value"], d["lat"]["value"] ] } } if "name" in d: f["properties"] = { "name": d["name"]["value"] } fs.append(f) return { "type": "FeatureCollection", "features": fs } def addLayer(rdftype, layername): gj = toGeoJSON(sparql(""" select ?uri ?name ?lat ?lng { ?uri <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <""" + rdftype + """>. optional { ?uri <http://www.w3.org/2000/01/rdf-schema#label> ?name. } ?uri <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?lat. ?uri <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?lng. } """)) #print(gj) post({ "originalName": layername, "transparency": 1, "windowNumber": 1, "data": gj }) addLayer("http://odp.jig.jp/odp/1.0#Polls", "odp 投票所") addLayer("http://odp.jig.jp/odp/1.0#PosterPlace", "odp 選挙ポスター掲示場") print("ok")

rdftypeに設定するデータ種別と対応地区は「5つ星オープンデータ対応一覧表」をご参照ください。


Tellus x オープンデータ、いろいろ遊んでみましょう!

宇宙と科学のシンポジウム、ISTS福井大会の展示期間が終了。IoT人流カウンターの値を集計してみました。

ほぼ一人ずつ通過する場所に設置し、精度良くデータが取れた、8Fの上りエスカレーター出口のデータを、10分置きにカウントをとって、簡易的にグラフにしたもの。

確かに人が少なかった月曜日の様子や、セッションのはじまり時間に合わせて流量が増えている様子がデータにも現れています。データを蓄積して、イベントデータと共に解析すると、優位な予測や、取り組みの効果測定に十分使えそうです。


こちら5日分のまとめ。


8Fに4箇所設置した、値を半分にして推定のべ人数としています。実際にはその場で立ち続けている人を重複カウントしたり、まとまって通った数を1として数えたりするので、あくまで目安です。

import csv def ana(fn, m, w): with open(fn) as csvfile: reader = csv.reader(csvfile) cnt = 0 bkd = None for row in reader: datetime = row[0] module = row[1] value = row[2] if m == module: #dt = datetime[0:13] # 1時間単位 dt = datetime[0:15] # 10分単位 if bkd is None: bkd = dt elif bkd == dt: cnt += 1 else: #w.write(bkd + "," + str(cnt) + "\n") # csv for 1時間単位 w.write(bkd + "0," + str(cnt) + "\n") # csv for 10分単位 bkd = dt cnt = 0 if not bkd is None: w.write(bkd + "," + str(cnt) + "\n") # csv fn = "ists-fukui2019.csv" modules = { "uZwuY2G0vn7C": "1FJ", # 1FJAXA内", # BSCM-B28 "uAbs00TuPz23": "5FR", # 5F展示 右", # BSCM-B94 "u52oJ7ReEICB": "5FL", # 5F展示 左", # BSCM-A00 "uXaXTQ866fqt": "8FU", # 8F上りエスカレーター", # BSCM-C07 "uKIpvNgHMhMZ": "8FD", # 8F下りエスカレーター", # BSCM-C12 "urBprjzYcYx8": "8FL", # 8Fエレベーター左", # BSCM-B27 "uHJqMGJf3tJ6": "8FR", # 8Fエレベーター右", # BSCM-B90 } for m in modules: print("analyze:", m, modules[m]) w = open("data-" + modules[m] + ".csv", "w") ana(fn, m, w) w.close()

人流センサーのローデータ CSV を解析するPythonプログラム(参考、Python3でCSVほか)


1F JAXAに設置していたカウンター(テレビの下)

IchigoJam x sakura.io を使った、IoT人流カウンターはオープンソース
福井x宇宙! 200円測距センサーとIchigoJamで作って実験、ISTS福井大会用、IoT入場者数カウンターとリアルタイムオープンデータ

観光地、施設出入り口、市役所の窓口など、いろいろ活用ください!
AI、EBPM、RPA、何を使うにしても、改善するなら、まずは計測しましょう!

やわらかセンサー「ショッカクポット」に続き、顔の画像認識を使った顔ポインティングデバイスをつくってみました。 顔を向けた方向にマウスカーソルが上へ動き、ゆっくりウィンクすると、クリック。前回と同様pyautoguiの遅さがちょっとネックですが、新鮮な操作感が楽しめました。

オムロンさんからお借りしている画像認識ハードウェア「HVC-P2」をUSBでMacにつないでPython3で接続! 顔の向き(上下左右傾き)、年齢、性別、視線の方向、右目つむり、左目つむりと表示させています。他にも喜び度合いや、顔認証などのサクッと使える機能があって、最大35名分をまとめて認識するのがすごい。


ヒューマンビジョンコンポ (HVC-P2) B5T-007001|製品紹介|オムロン人画像センシングサイト:+SENSING
製品情報タブから、コマンド仕様書をダウンロードできます。 シンプルなシリアル通信で、簡単接続!カメラで撮影した、画像データの取得もリクエスト時の設定で可能です。(src on GitHub

import serial ser = serial.Serial('/dev/tty.usbmodem11', 921600, bytesize = serial.EIGHTBITS, parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE) ser.write(0xfe.to_bytes(1, 'little')) ser.write(0x00.to_bytes(1, 'little')) ser.write(0x00.to_bytes(2, 'little')) ser.flush() fe = int.from_bytes(ser.read(), 'little') # recv 0xfe n = int.from_bytes(ser.read(), 'little') # res code len = int.from_bytes(ser.read(4), 'little') # len for i in range(len): print(ser.read())

ID受信するプログラム in Python3、シンプルですね!
IchigoJamなど、UART接続する場合、このケーブルが使えそう?
PRT-10361 JST SHコネクタ付ケーブル 6P (基板用ポスト付属)


画像認識ハードウェアをラズパイで自作するのも楽しいですね!


ラズパイマガジン 2019年4月号、特集「ラズパイ&人気ボード20枚」に、IchigoJam, IchigoLatte がランクイン!

適材適所、いろんなハードウェアを使いこなして、創りたいもの創りましょう!
創ってできたオリジナル製品、秋葉原に新登場した明和電機のリアルショップ「ラジオスーパー@ラジオデパート2F(未掲載、2F桜屋電機向かい)」での販売もいいですね!

一日一創オープンソースハードウェア「光るネクタイ」が、Hana道場発プロダクトとして、販売開催!
初日から大盛況! 明和電機の公式ショップがついにオープン (取材中に見つけた○○なもの) - AKIBA PC Hotline!

早速、第二期募集スタート!
第二期 ラジオスーパー応募要項 - 明和電機 - Maywa Denki明和電機 – Maywa Denki

化粧用スポンジの収縮を計測する変わり種センサー「ショッカクポット」を使ったやわらかボタン。 シリアル通信で使え、3.3Vでも動いたので、PC用のUSBシリアルを経由してマウス替わりのポインティングデバイスにしてみました。

やわらかい触り心地の新操作感、小さなこどもから、高齢者、障害者の方まで、幅広く提供する、インクルーシブソフトウェアとしてもオススメです! ThinkPadの赤いポインティングデバイスをご存知の方には、大きくなって、柔らかさが増した感じというとわかりやすいかも。


ショッカクポットの5V、GND、Tx、Rx、RSTを、3.3V(定格外ですが)、GND、RXD、TXD、DTSに接続すればハードウェアの準備はOK!

今回は、Python3でプログラムを書きました。

serport = '/dev/tty.SLAB_USBtoUART' import time, serial ser = serial.Serial(serport, 57600, bytesize = serial.EIGHTBITS, parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE) ser.dtr = True #reset time.sleep(0.1) ser.dtr = False time.sleep(0.1) ser.write('m'.encode('utf-8')) ser.read() # dummy recv 0xff time.sleep(0.1) import pyautogui try: data = [ 0, 0, 0, 0 ] # 10bit date: CH1, CH4, CH2, CH3 while True: ser.write(0x6d.to_bytes(1, 'big')) ser.flush() sum = 0 for i in range(4): n = int.from_bytes(ser.read(2), 'big') data[i] = n sum += n print(data) # drive Shokkaku pot! if sum / 4 > 40: pyautogui.click() else: dx = (data[3] - data[0]) / 2 dy = (data[1] - data[2]) / 2 dx = dx * abs(dx) dy = dy * abs(dy) pyautogui.move(dx, dy) except KeyboardInterrupt: ser.close()

pyserial, pyautogui を pip3 でインストール!
# drive Shokkaku pot! の下を書き換えるといろいろ好きに使えます
つまむ動作を認識して、特定の動作に対応させるのも、楽しそうです!


pyautogui.move の動作がちょっとぎこちないのが残念・・・。重いので自乗して簡易的に加速させています。java.awt.Robot版ともいいかも。

何事もまずは試作。山口県訪問時に買ってきた瓦そば。山口では家庭でフライパンやホットプレートで作って食べるのが一般的とのことなので、挑戦してみました。
高専生活躍! 異分野 x アプリ/IoTが熱い、G空間ハッカソン in 山口

一番の難関は錦糸卵。初挑戦に選んだ参考書はこちら
簡単すぎてウソみたい!失敗しない錦糸卵の作り方&春色アレンジレシピ3選♩ - macaroni

卵液を初回は全部いれてしまい分厚くなって失敗。2度目は裏返し忘れて失敗。3度目は焼き具合はよかったものの、細く切る技術が足りずそこそこなでき。「ひとつまみ」という、謎料理単位に悩みましたが、前進あるのみ。


牛肉を先に焼いておき、ゆでて水でしめて、ザルで水切りした茶そばを炒める。やきそばと違って、あまりかき混ぜず、焼く感じがポイントと知ったのは作った後。 確かに、本場で食べた瓦そば、下の方はカリカリしてました。その触感の違いもまた特徴とのこと。


ネギ、ノリ、レモン、もみじおろしを省略、しかも卵と肉が逆だった、第一試作でしたが、おいしかった!
次は、フルバージョンにチャレンジしたい!(Amazonにありました他多数

links
- タッチエンスのショッカクポット(POTU-001-1)を触ってみた。 - Qiita
- やわらかIoTボタンとバーチャルリアリティ VR ZONE SHINJUKU体験で想うVRゲーセンの未来形
- ショッカクポットI2C版 - Amazon

日本の宇宙オープンデータ時代の幕開け!
宇宙(ソラ)からの目、衛星データを無償提供する、Tellus OS ver 1.0 公開記念イベント。
目標は、現在の日本の宇宙関連市場1.2兆円を2030年までに倍の2.4兆円!

Tellus SPACE xData Fes.
Tellusが提供するオリジナルの衛星データなどは、ユーザー登録、原則コピー不可な、非オープンデータですが、 二次成果物の利用は自由となっているので、オープンデータ化することが可能です(利用規約に一部条件あり)。 また、エンドユーザーに有償で利用させる場合(利用規約)は、別途アグリーメントが必要。


さくらインターネット社長、舞鶴高専の高専違いの1つ上の先輩、田中さんによるオープニング!
公開したら終わりの従来ソフトウェアではなく、プラットフォームなので、ここからが本当の始まり。
膨大なデータを解析するための環境も用意し、宇宙データを使う敷居をぐっと下げる。
小学生でも活用しちゃうかも!?


世界最高水準50cmの分解能の衛星写真(光学)と、雲を透視でき植生などが分かる電波の反射による地上観測データ(SAR)が、無償で閲覧可能になりました!(画像提供、さくらインターネット)


宇宙 x ??、トークセッション1に登壇。
夏野さん、お久しぶりです!日本中のオープンデータ、全部Tellusに入れちゃう案、大賛成。
ガラパゴスにならない世界連携プラットフォームを創る最後のチャンス!
夏野さん、これからのベンチャーに何が必要ですか? (impress QuickBooks)


夏野さんの宇宙事業へのアドバイスは「派手に」
TELLO EDU 操縦用プログラムによる、自動撮影デモにで撮れた映像です。
新しいソラからの目、衛星とドローンとは補完関係。
(Python3による自動撮影プログラムは末尾参照)


宇宙 x アートが熱かった、トークセッション2
高解像度な宇宙アート写真が3,000万円! 月や火星などへの第二次宇宙ブーム、未知への憧れ、再び!


衛星画像データから、船が動いているか、停まっているか、艀(はしけ)かをいかに認識できるか競った、賞金総額200万円のAI画像認識コンテストの総評。
ロシア人プログラマーのNick Sergievskiyさんによる最優秀モデルで、56.7%と、なかなか難問だった様子。(最終評価で47.5%?)
コンペティション詳細/Tellus Open&Free Platform / 経済産業省 | SIGNATE - Data Science Competition


こちら、正解データ。3種類を高精度で見分けるモデルをいかに作れるか?


分割して、回転させたりジッターしたりで学習用画像を水増し、よく効くと噂の Faster-RCNN でモデルを組んで、機械学習!
上位はみんな類似のモデルだったそうです。(使用言語は、ほぼPythonほぼDeep Learning


THETAで撮った小笠原さんによる乾杯!宇宙っぽく丸く。広い会場、満員な上に椅子増席という人気!


懇親会時に開催された、Tellus SPACE アイデアワークショップ!
宇宙データと地上データをマッシュアップして何作ろう!?


宇宙感!


xData SPACE Fes. 会場向かいは、東京タワー。
今日、この遥か上空からの見下ろす「宙(ソラ)の目」を、誰もが獲得したわけです。
さて・・・あなたは何を見る?

links
- 2019年2月リリース! 衛星データプラットフォーム「Tellus」でできること | 宙畑 (SORABATAKE)
- 衛星データを無料で活用できるクラウドサービス「Tellus」、さくらインターネットが開始 | IT Leaders
- ASCII.jp:衛星データプラットフォーム「Tellus」が運用開始
- 衛星データを無償公開 さくらインターネット  :日本経済新聞
- 政府、衛星データを無料提供 新ビジネス創出を期待 - 毎日新聞
- 衛星情報の無料開放始まる 様々なサービスに期待
- 衛星データ“無料開放”サービス|NHK 首都圏のニュース
- 衛星データの”開放”は成功するのか? | 新・科学の世紀 | NHKオンライン
- さくらインターネット、クラウド上で衛星データの分析ができる日本初の衛星データプラットフォーム「Tellus(テルース)」を運用開始|さくらインターネット株式会社のプレスリリース
- 宇宙オープンデータ活用アライアンス「xData Alliance」参画! オープンデータで理解する大気圏、成層圏、対流圏
- 宇宙からのデータ活用で社会が変わる!衛星データプラットフォーム「Tellus(テルース)」発表
- 【イベント】日本の宇宙ビジネスを加速させる日本初の衛星データプラットフォームが公開!「Tellus(テルース)」記者発表会 | さくらインターネット
- 宇宙データはイノヴェイションの新たなトリガーだ!:Tellus SPACE xDATA Fes.で語られたこと|WIRED.jp

TELLO EDU による、360度自動撮影 Python3 プログラム

import threading import socket import sys import time event = threading.Event() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) tello_address = ('192.168.10.1', 8889) sock.bind(('', 9000)) def recv(): while True: try: data, server = sock.recvfrom(1518) print(data.decode(encoding = "utf-8")) event.set() except Exception: print('Exit recv') break recvThread = threading.Thread(target = recv) recvThread.start() def send(command): msg = command.encode(encoding = "utf-8") sent = sock.sendto(msg, tello_address) event.wait() event.clear() import cv2 import datetime def getNow(): return datetime.datetime.today().strftime("%Y%m%d%H%M%S") takepicture = False def takePicture(): global takepicture takepicture = True print("take a picture") videowriter = None def startMovie(): global videowriter if videowriter is None: FPS = 30.0 SIZE = (960, 720) FOURCC = cv2.VideoWriter_fourcc(*'mp4v') videowriter = cv2.VideoWriter("cap/" + getNow() + ".mp4", FOURCC, FPS, SIZE) print("start movie") def stopMovie(): global videowriter if videowriter is not None: vw = videowriter videowriter = None vw.release() print("stop movie") cap = None def capture(): global cap while not cap.isOpened(): time.sleep(0.1) while True: if cap is None: break ret, frame = cap.read() if frame is not None: global takepicture if takepicture: cv2.imwrite("cap/" + getNow() + '.jpg', frame, [ cv2.IMWRITE_JPEG_QUALITY, 95 ]) takepicture = False global videowriter if videowriter is not None: videowriter.write(frame) def startCapture(): global cap cap = cv2.VideoCapture('udp://127.0.0.1:11111') capThread = threading.Thread(target = capture) capThread.start() def endCapture(): global cap if cap is not None: tcap = cap cap = None tcap.release() send("command") send("streamon") print("stream on!") startCapture() startMovie() send("takeoff") takePicture() send("up 200") send("flip f") send("cw 360") send("flip b") send("land") stopMovie() endCapture() sock.close()

PM2.5が気になる季節、以前作った福井PM2.5 APIを使って、しゃべるPM2.5計スマートスピーカー Google Home Mini版を作ってみました。 人感センサーをつけて、朝一のリビングに入った時などに、しゃべってもらうといい感じかも。

Google Home を、ただのネットワークスピーカーとして使いたいときには、google-home-notifier。 再生してほしいmp3の音声ファイルのURLを渡すと通知して鳴らしてくれるというシンプルなもの。

PM2.5の値を取得し、しゃべらせたい文章を作成、Mac標準の音声合成コマンド say を使って、音声ファイルを作って、ffmpegでmp3化して、ローカルで立てたwebサーバーに設置して、Google Home Mini へ通知を送ればできあがり!

saypm25.py - PM2.5 APIから鯖江市神明の値を取得し、次へ

import os import urllib.request url = 'http://sabae.club/pm25/1/fukui/sabae.txt' req = urllib.request.Request(url) with urllib.request.urlopen(req) as res: body = res.read() n = int(body) print('response: ' + str(n)) s = 'おはようございます!鯖江市神明地区で計測したPMにぃてんごの値は、' + str(n) + 'です。' if n <= 70: s += '不要不急の外出は避けましょう。' os.system('./say-google.sh "' + s + '"')

say-google.sh - 日本語をmp3音声ファイルに変換して、次へ(ローカルwebサーバーの所定pathを設定)

say -v Kyoko $1 -o say.aiff ffmpeg -y -i say.aiff say.mp3 cp say.mp3 [** path ** ]/ node say.js

say.js - google-home-notifier を使って、通知する(ローカルwebサーバーの所定URLを設定)

const googlehome = require('google-home-notifier') googlehome.device('Google Home', 'ja') googlehome.play('http://[** ip, port, path ** ]/say.mp3', function(res) { console.log(res) })

毎朝、決まった時間にしゃべらせるなども、カスタマイズしましょう。

小さくても、結構大きな音がでる Google Home Mini、イベントや、ハッカソンなどでも活用できそうです。

G空間ハッカソンで活躍した、webアプリハンズオン研修、来週、福井市で再び開催!
G空間オープンデータで地図アプリ作成ハンズオン - connpass

links
- PM2.5時計(鯖江編)
- 玄関先でPM2.5の値を教えてくれる音声合成を使ったIoTデモ

人気のプログラミング言語、Pythonを使ったリアルタイム画像処理と思って、Macのカメラを読み込み、とりあえず画面に表示するだけプログラムをつくるも、フレームレートが著しく悪い。カクカクして、これでは興ざめ。

import cv2 cap = cv2.VideoCapture(0) print("fps: " + str(cap.get(cv2.CAP_PROP_FPS))) while True: ret, frame = cap.read() frame = cv2.flip(frame, 1) # horizontal flip cv2.imshow("esc key to close", frame) k = cv2.waitKey(1) if k == 27: break cap.release() cv2.destroyAllWindows()

Djangoより、シンプルなwebアプリフレームワーク Flask を使って、ブラウザで表示するととっても滑らかになりました!

左右反転させるだけのただの鏡アプリです。
画像認識してネコ耳を上書きしたり、背景を消したり、いろいろ遊ぶテンプレートとして活用ください。

import cv2 from flask import Flask, Response app = Flask(__name__) webcamid = 0 cap = cv2.VideoCapture(webcamid) print("fps: " + str(cap.get(cv2.CAP_PROP_FPS))) def getFrames(): while True: ret, frame = cap.read() frame = cv2.flip(frame, 1) # horizontal flip ret, jpg = cv2.imencode("test.jpg", frame) yield b'--boundary\r\nContent-Type: image/jpeg\r\n\r\n' + jpg.tostring() + b'\r\n\r\n' @app.route('/') def video_feed(): return Response(getFrames(), mimetype='multipart/x-mixed-replace; boundary=boundary') import webbrowser webbrowser.get().open("http://localhost:5001/") app.run(host = '0.0.0.0', port = 5001, threaded = False) # only 1 client

ブラウザを開くコードもついているので、Python3で動かすと、ブラウザが開いてすぐに表示が始まります。
Content-Type: multipart/x-mixed-replace は、初めて使いましたが、なかなか豪快なプロトコルでおもしろい!
複数開いて問題が置きないように、Flashの設定で threaded = False として、シングルスレッド処理としています。

スレッドモデルなプログラミング言語 Python の yield がポイントです。

Tweet
クリエイティブ・コモンズ・ライセンス
この作品は「Creative Commons — CC BY 4.0」の下に提供されています。
CC BY 福野泰介 - Taisuke Fukuno / @taisukef / アイコン画像 / プロフィール画像