360°画像を用いたリハビリを目的とする Mixed Reality デバイスの開発

新年のご挨拶
あけましておめでとうございます。そして大変ご無沙汰しておりました。言い訳しますと、OSHWなものづくりの傍ら塾の先生と学校のICT支援員をしているのですが、昨今のコロナ禍でてんやわんやの混沌でして。

尚mRNAワクチンに関する話やCOVID19の振る舞に関して情報を収集しているうちにDIYバイオに関してもいくつか思いついたものがありますので、今後はそっちも整理してぼちぼち公開していければいいなと思います。

例えばチューリングマシン互換のDNAコンピュータの原理を思いついてしまったり。気が付いたのですが、DNAの発現プロセス(セントラルドグマ)と逆転写系(クリックさん残念)をセットで捉えてDNAをテープに見立てるとチューリングマシンそっくりです。加えてチューリングマシンのテープは無限長ですが、アドレス指定は離散数で行うことから無限長のDNA(データはATGCの4種の塩基で記述され離散的)を考えれば無限の濃度が等しいので等価となるはず。書き込み系はCRISPR-Cas9みたいな使い勝手が良いものを使えば良い。課題は読み取り系でこっちはリボソームの改変でいずれ何とかなるか?この新型DNAコンピュータの利点はサイズ(細胞ないしそれ未満のスケール)。不利点は処理速度と野生化した場合のリスク(野生化するコンピュータというと神林長平の「今宵、銀河を杯にして」みたいでわくわくします)。私は何を言っているんだ。

※ 生命現象と計算機を関連させる発想については「銀河ヒッチハイクガイド」あたりの影響もありそう
※ スーパーフレアやガンマ線バーストなどの天文災害による電子機器の大規模な破壊を想定するなら電子式以外のそれなりに高性能な自動式計算機・情報処理装置があるといいなと思っています(杞憂)

あとは中途になっている拙作の各種プロダクトの開発の続き。長期間放置してしまい本当に申し訳ありませんでした。パーツをそろえつつ順次再開出来ればと存じます。

本題
さて、本年1回目の投稿ですが、知人のリハビリ用に開発していたMR(Mixed Reality)デバイスがそれなりに形になってきたので設計っぽいものをCC-BY-SAで公開します。
退屈であったり時に苦痛を伴う日々のリハビリにエンターテイメント性・ゲーム性を持たせることで使用者の精神的な負担を軽減することを狙いとしています。

原理は単純で、運動器具からの入力をロータリーエンコーダーで拾い360°画像(360 degree equirectangular)の表示を追従させています。しくみは天体望遠鏡の赤道儀とか、チャップリンの独裁者の冒頭で出てくる高射砲の操作系とかから発想しました。

ハードウェアの設計っぽいもの
CC-BY-SAでどうぞ。

・ロータリーエンコーダーで運動器具の回転量を検出。
・ロータリーエンコーダーからの入力をラズパイのGPIOへ。

ラズパイ(Raspberry Pi)は一応クローズドなハードなのでいずれ何らかのオープンな奴で置換したい。

制御ソフトウェア

import tkinter as tk
import numpy as np
from PIL import ImageTk
from PIL import Image
import Encoder
import py360convert

#equi_image = "/var/tmp/example_input.png"
equi_image = "/var/tmp/sample_equirectangular.jpg"

equi_image_array = np.array(Image.open(equi_image))
h_fov = 75.2
v_fov = 60
out_w = 640
out_h = 480
equi_in_rot_deg = 0
equi_mode = "bilinear"
class SimpleApp(object):
    def __init__(self, master, imagedata, **kwargs):
        self.master = master
        self.imagedata = imagedata
        self.canvas = tk.Canvas(master, width=out_w, height=out_h)
        self.canvas.pack()

        self.update = self.draw().__next__
        master.after(50, self.update)

    def draw(self):
        enc_1 = Encoder.Encoder(24, 10)
        image = self.imagedata
        while True:
            tkimage = ImageTk.PhotoImage(image)
            canvas_obj = self.canvas.create_image(
                out_w//2, out_h//2, image=tkimage)
            self.master.after_idle(self.update)
            yield
            self.canvas.delete(canvas_obj)
            xvalue = enc_1.read()
            yvalue = 0
            print(str(xvalue) + ',' + str(yvalue))
            equi_out = py360convert.e2p(equi_image_array, fov_deg=(h_fov, v_fov), u_deg=xvalue, v_deg=yvalue,
                out_hw=(out_h, out_w), in_rot_deg=equi_in_rot_deg, mode=equi_mode)
            image = Image.fromarray(equi_out.astype(np.uint8))

equi_out_begin = py360convert.e2p(equi_image_array, fov_deg=(h_fov, v_fov), u_deg=0, v_deg=0,
    out_hw=(out_h, out_w), in_rot_deg=equi_in_rot_deg, mode=equi_mode)
image_data = Image.fromarray(equi_out_begin.astype(np.uint8))
root = tk.Tk()
app = SimpleApp(root, image_data)
root.title("バーチャルお散歩・リハビリアプリ")
root.attributes("-fullscreen", True)
root.bind("<F11>", lambda event: root.attributes("-fullscreen",
                                    not root.attributes("-fullscreen")))
root.bind("<Escape>", lambda event: root.attributes("-fullscreen", False))
root.mainloop()

外部パッケージの「numpy」、「Encoder」及び「py360convert」を使用しています。
本コードは Stack Overflow に投稿されたいくつかのコードを下敷きに書きました。よってCC-BY-SAでどうぞ。
※後ほど出典を整理しアップします

動作の様子
クランクの回転に追随して画像が変化します。
※後ほど動作の様子の動画をアップします

お詫び
配慮を欠き大変申し訳ありません。時間をおいて読み返したところ、路悪趣味だとしても許容されるべきでないと思われる表現がありましたため該当表現を削除致しました。

「いいね!」 1