2016-08-28[n年前へ]
■ダイソー100円4弦ギターに振動ピックアップを取り付けて、PCやスマホで化粧させつつ遊んでみる!?
100円ショップの「ミニ竹製ものさし+輪ゴム」セットにアンプを付けて、で沖縄三線気分に浸ってみるで物体の振動をピックアップする回路を作ったので、今日は100円ショップのダイソーに行き、消費税込みトータル108円でギターみたいなマンドリンみたいな4弦の楽器玩具を買ってみました。
ダイソー4弦100円ギター風で/マンドリン風でもある玩具楽器に、Maker Faire Tokyo 2016 で見かけた振動ピックアップマイク回路を取り付けて、その振動信号をノートPCで適当に超化粧させてみた録音動画が下に貼り付けたファイルになります。…ちなみに、録音作業は風呂場にノートPCと100円4弦ギターを持ち込んで、適当にジャカジャカ弾いてみたのですが…単三電池4本の回路なら、お風呂でギターな感電死なんて発生しないデスよね?
2017-01-29[n年前へ]
■「手持ちスマホ撮影動画からの超巨大開口レンズ撮影」に挑戦してみよう!?
かつて、スマホに搭載されているカメラのレンズはとても小さく、綺麗なボケとは無縁の存在でした。しかし、今や最新のスマホには特殊処理によるボケ生成機能などが備えられています。カメラレンズの光学開口径が小さくとも、たとえば2眼カメラなどを備えて距離情報を取得して、距離情報などからボケを人工的に合成するといった仕組みです。
そんな最新スマホを持たずとも、大レンズのボケ味を手に入れるために、「手持ちスマホ撮影動画からの超巨大開口レンズ撮影」に挑戦してみました。スマホ動画から巨大開口レンズ撮影の手順はとても簡単、まずは目の前の風景にスマホを向けて・なるべくスマホが平面上を動くように意識しながら(スマホを動かしつつ)動画撮影します。そして、動画の各コマから画像ファイル群を生成し、それぞれの画像が撮影された位置や方向にもとづいて撮影された光情報を加算合成する、というものになります。
細かい手順は、スマホ撮影動画(の展開画像をもとに) Bundler: Structure from Motion (SfM) から出力された刻々のカメラ位置・方向や特徴点情報ファイル(bundler.out)を読み込み、それらのカメラ情報にもとづいて、刻々の撮影画像をレンズ開口面に沿った(同じ方向を向く平行カメラが存在していた場合の)光線画像を位置・角度ズレを踏まえて重ねることで、任意のピント位置に焦点を合わせた超巨大開口レンズ撮影画像を生成する…というものです。
試しに、iPhoneを約1.5m×1.0mの範囲で動かしつつ動画撮影し、つまり、レンズ直径約1.5mに相当する範囲で動かしつつ動画撮影し、その画像群から開口合成により超巨大カメラの撮影画像を作り出してみた結果が右上の画像です。
右上画像を眺めてみても、良好なボケ味どころか、全くピントが合っていない画像にしか見えません。直径が1mを超える開口を持つカメラレンズとなると焦点深度もとても浅くなるのでピントがなかなか合わない…というわけでなく、手持ち撮影動画からのカメラ位置・方向精度が低いせいか、単一カメラに平行合成した後のズレが大きいようです。
ちなみに、試しに各画像を(撮影方向による傾きを補正しつつ)位置毎に並べてみると、下の画像のようになります。動画撮影からのカメラ位置推定精度が果たして不十分なのかどうか、次は撮影カメラ位置を精度良く知る事ができる撮影治具でも作り、また再挑戦してみたいと思います。
上記処理のコード手順、Python/OpenCVで書いたコード処理手順は、bundler.outからカメラ位置・方向・焦点距離や歪みパラメータを読み込み、cv2.initUndistortRectifyMapにカメラ情報を渡して、各撮影画像の向き補正用のホモグラフィーマップを作成してremapで変換した後に、各撮影画像を加算合成するという手順です。
Bundlerの出力ファイルを読み込んでライトフィールド合成を行うOpenCV/Pythonコード、まだまだ間違い含まれているような気もしますが、とりあえずここに貼り付けておくことにします。
import cv2 import numpy as np from matplotlib import pyplot as plt from PIL import Image import math %matplotlib inline class camera: def __init__(self): self.f = 1.0 self.k1 = 0.0 self.k2 = 0.0 self.R = [[0.0,0.0,0.0],[0.0,0.0,0.0],[0.0,0.0,0.0]] self.T = [0.0,0.0,0.0] def readBundlerOut( filePath ): f = open(filePath, 'r') list = f.readlines() f.close() numberOfCameras = int((list[1].split())[0]) cameras = [] for i in range(numberOfCameras): aCamera = camera() fk1k2 = [float(j) for j in list[5*i+2].split()] aCamera.f = fk1k2[0] aCamera.k1 = fk1k2[1] aCamera.k2 = fk1k2[2] rot = [] for j in range(1,4): rot.append( [float(k) for k in list[ 5*i+2+j ].split()] ) aCamera.R = rot aCamera.T = [float(k) for k in list[ 5*i+2+4 ].split()] cameras.append(aCamera) return cameras def readImageList( listPath, imageDirPath ): f = open(listPath, 'r') list = f.readlines() list = [ i.rstrip() for i in list ] f.close() list = [imageDirPath+fileName for fileName in list] return list class lightField: def __init__(self): self.w = 2000 self.h = 2000 def loadImageListAndMakeLightField( self, imagePathList, cameraList, workList, scaleA ): self.cimg = np.zeros((self.h, self.w,3), dtype=np.uint8) sum = 1.0 for i in workList: img = cv2.imread( imagePathList[i], cv2.IMREAD_COLOR ) h, w = img.shape[:2] imageHeight = img.shape[0] imageWidth = img.shape[1] focalLength = cameraList[i].f principalPointX = 0.500000 principalPointY = 0.500000 distCoef = np.array([ 0.0, 0.0, 0.0, 0.0, 0.0 ]) cameraMatrix = np.array([ [focalLength, 0.0, imageWidth * principalPointX], [0.0, focalLength, imageHeight * principalPointY], [0.0, 0.0, 1.0] ]) newCameraMatrix, roi = cv2.getOptimalNewCameraMatrix( cameraMatrix, distCoef, (img.shape[1], img.shape[0]),1, (img.shape[1], img.shape[0]) ) rotMatrix = np.array( cameraList[i].R ) map = cv2.initUndistortRectifyMap( newCameraMatrix, distCoef, rotMatrix, newCameraMatrix, (img.shape[1], img.shape[0]), cv2.CV_32FC1) undistortedAndRotatedImg = cv2.remap( img, map[0], map[1], cv2.INTER_LINEAR ) scale = 1.0 pt3 = np.array(cameraList[i].T) - np.array(cameraList[0].T) x = ( self.w/2.0 - pt3[0] * scale * scaleA ) y = ( self.h/2.0 - pt3[1] * scale * scaleA ) pts1 = np.float32( [[0, 0], [w, 0], [w, h], [0, h]]) pts2 = np.float32( [[x, y], [x + w*scale, y], [x + w*scale, y + h*scale], [x, y + h*scale]] ) M = cv2.getPerspectiveTransform( pts1, pts2 ) img2 = cv2.warpPerspective( undistortedAndRotatedImg, M, (self.w, self.h) ) sum = sum + 1.0 self.cimg = cv2.addWeighted( self.cimg, (sum-1) / sum, img2, (1.0) / sum, 0) def showImage(self): plt.figure( figsize=(14,14) ) plt.imshow( np.array(self.cimg2) ) plt.autoscale( False )
2017-03-05[n年前へ]
■現実のリアルタイム風景と、そこから眺めた好きな時間・瞬間を合成してVR的に眺めてみよう!?
先日、周囲全方向を撮影することができるRicoh Theta Sを使い、24時間にわたり11段階の多段露出撮影画像からリトル・プラネット(とても小さな星を上空から撮影したような)風動画を作ってみました(Ricoh Theta S で24時間のHDR(多段露出)撮影をして遊んでみる!?)。けれど、そんな風に景色を離れたところから第三者的・客観的に眺めるのではなくて、その場に立って一人称的に景色を眺めたくなりました。そこで、合成した高画質4K動画をYoutubeに(360度映像だというタグを付けて)アップロードしてみました。
こうすることで、スマホからYoutubeアプリケーションでアクセスし、VR用レンズセットを取り付けて眺めれば、あたかもこの場所に立ち・数百倍近く速く時間が流れる中で、夜空や太陽の影を眺めることができます。
そして一番面白いのは、24時間の撮影を行った場所に立って、目の前にあるリアルタイムな実際の景色を眺めつつ、「東の空に昇る太陽や夜星や夕焼けや」…24時間の中にある美しい瞬間や一番好きな時間を、スマホに覗いて自由自在にVR合成しながら眺めてみると…とても不思議で面白い気持ちになってきます。
今日は、24時間にわたる、周囲全ての4πステラジアンの全天周風景を、11段階多段露出のハイダイナミックレンジ撮影をして、その映像を4K映像に変換して眺めてみました。
2017-04-07[n年前へ]
■OpenFOAMの流体シミュレーション世界、手持ちのスマホで没入体験してみよう!
以前、OpenFOAMを使ってシミュレーション計算した、秋葉原の街全体に吹く空気流。その時は、Oculusで没入的に眺めてみた。今日は、スマホで普通にVR没入体験できるよう、スマホ用アプリケーション化してみた。
最初は、最近公開されたばかりのUnity 5.6のネイティブなVR機器サポートを使おうと思ったのだけれど、iOS向けのビルドでリンカエラーが出て回避できなかったので、Unity 5.5.3f1+Google VR SDK for Unity v1.0.3で仕立ててみました。
2017-04-15[n年前へ]
■続 OpenFOAMの流体シミュレーション世界、手持ちのスマホで没入体験してみよう!
少し前、大規模な流体計算シミュレーションを行った結果の中に、スマホをVRデバイスとして入り込む…というOpenFOAMの流体シミュレーション世界、手持ちのスマホで没入体験してみよう!(を書いた。これを作るにいたったキッカケは、「秋葉原の街中全体を空気流計算するのは面白い」「けれど、ふつうの人が持ってないヘッドマウントディスプレイだけでしか見ることができないのはツマラナイ!」「空気流れる空に向かって飛んでみたい!」というコメントをもらったことだった。
このコメントは確かにその通りだ。1家に1台…ならぬ今や1人1台誰もが持っているスマホを使って流体シミュレーション世界に入り込む(没入体験する)ことができたなら、それは確かにとても面白いに違いない!というわけで、流体シミュレーション世界にスマホを使って没入体験するための作業をしてみたのです。
「秋葉原の街中全体を空気流計算するのは面白いけれど、ふつうの人が持ってないヘッドマウントディスプレイだけでしか見ることができないのはツマラナイ!」というコメントがもっともなのと同じように、「空気流れる空に向かって飛んでみたい!」というコメントも、確かにその通りとしか言いようがありません。
…というわけで、今日はその「空気流の中を飛び回りたい」という要望もに応えるための対応作業をしてみました。
そんな作業をしてみたら、偶然というものは恐ろしいもので、まさに今日は『第64回オープンCAE勉強会@関東(流体など)』が会場【秋葉原】で開催されています。
秋葉原を流れる空気を流体計算し、その場所に立ちVR/AR的に流体計算結果を眺めることができて、その秋葉原で今日まさに流体計算の集いが開かれている!?…というわけで、スマホで秋葉原空気流のVR表示を行う話を、今日は秋葉原で紹介してみました。