Node.jsのインストール
Node.jsのインストール
Mac
homebrewをupdate
brew update
nodebrewをインストール
brew install nodebrew
nodebrewをセットアップ
nodebrew setup
node.jsをインストール
nodebrew install latest
Windows
- https://nodejs.org/en/
インストーラーでインストールする。
UnityのTransfrom.Find()について
UnityのTransform.Find()について
2018/03/15, Unity2017.3.0f3
子のオブジェクトを文字列で取得するメソッド。
https://docs.unity3d.com/ScriptReference/Transform.Find.html
公式リファレンス(2017.3)では、以下のようにディレクトリのパスのように記述することで深いところにある子まで取得できると書いてあるが、この書き方では取得できなかった。
//Find the child named "ammo" of the gameobject "magazine" (magazine is a child of "gun"). ammo = gun.transform.Find("magazine/ammo");
下のように親の名前は書かずに最初の子からのパスを書くことでちゃんと動いた。
//parent // -child // -child2 transform.Find("child/child2")
C#でフィールド名をすべて取得する
C#でフィールド名をすべて取得する
using UnityEngine; using System.Reflection; User user = new User(); FieldInfo[] infoArray = user.GetType().GetFields(); foreach (var info in infoArray) { Debug.Log(info.Name + ":" + info.GetValue(user)); }
参考
Gitの使い方まとめ
Gitの備忘録
基本的な使い方
初期化
> git init
リモートリポジトリを追加
> git remote add origin https://hogehoge # 削除 > git remote rm otigin
コミット
> git add [file] # 新規、変更、削除をすべて > git add -A # 変更、削除をすべて > git add -u # 新規、変更をすべて > git add . > git commit -m ["message"]
コミットの削除
# 作業ツリーを維持(HEADだけ) > git reset --soft HEAD~ # 作業ツリーを維持(インデックスも) > git reset HEAD~ # 作業ツリーも削除(全部) > git reset --hard HEAD~
コミットの打ち消し
> git revert [commit]
プッシュ
> git push origin master
コミットの結合
> git rebase -i HEAD~3
なんとなく使い方が英語で出てくる
HEAD~3はブランチ先頭から3コミットという意味
確認系
# 変更点 > git status # ログ > git log # 便利 > git log --online
参考
- https://qiita.com/muran001/items/dea2bbbaea1260098051
- https://qiita.com/wwacky/items/2f110ee76fc1cb681c3b
- https://dev.classmethod.jp/tool/git/git-rebase-fixup/
- http://www-creators.com/archives/1116
- https://git-scm.com/book/ja/v1/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E5%B1%A5%E6%AD%B4%E3%81%AE%E9%96%B2%E8%A6%A7
PythonでWebスクレイピング
PythonでWebスクレイピング
from urllib.request import urlopen from html.parser import HTMLParser class MyHTMLParser(HTMLParser): def handle_starttag(self, tag, attrs): print "Encountered a start tag:", tag def handle_endtag(self, tag): print "Encountered an end tag :", tag def handle_data(self, data): print "Encountered some data :", data url = "https://hogehoge" html = urlopen(url).read().decode("utf-8") parser = MyHTMLParser() parser.feed(html)
参考
PHPの備忘録
PHPの備忘録
<?php //コメントアウト /* 複数行コメントアウト */ define("NAME", "VALUE"); function fizzBuzz(){ for($i = 1; $i <= 100; $i++){ if ($i % 3 == 0) { echo 'Fizz'; } if ($i % 5 == 0) { echo 'Buzz'; } if (!($i % 3 == 0) && !($i % 5 == 0)) { echo $i; } echo "\n"; } } abstract class Vector2{ protected $x; protected $y; function __construct($x, $y){ $this->x = $x; $this->y = $y; } abstract function toString(); } class Vector3 extends Vector2{ private $z; function __construct($x = 0, $y = 0, $z = 0){ parent::__construct($x, $y); $this->z = $z; } function toString(){ //文字列の中に変数をかける return "($this->x, $this->y, $this->z)"; } function Hoge(){ return true; } } $origin = new Vector3(); echo $origin->toString(); //(0, 0, 0) //文字列の変数からクラスのインスタンスを作ったり、関数を呼び出すこともできる $vector3String = "Vector3"; $toStringString = "toString"; $one = new $vector3String(1, 1, 1); echo $one->$toStringString(); //(1, 1, 1) ?>
WindowsでPHPをローカルで動かす
WindowsでPHPをローカル環境で動かす方法
このサイトでXAMPPをダウンロードする。 www.apachefriends.org XAMPPとは最も人気のある開発環境(Apacheディストリビューション)だそうです。
ダウンロードしたら起動して ApacheのActionsのStartを押すだけ、あとはlocalhostにアクセスするとデフォルトのページが見えるはず。 位置はC\:/xampp/htdocs
参考
3SATがNP完全であることの証明
はじめに
CNF論理式とは
リテラル(論理変数またはその否定)の論理和である節の論理積からなる論理式
CNF論理式:
リテラル:
節:
SAT問題とは
あるCNF論理式を真にするようなリテラルの組み合わせは存在するかどうかの充足可能性問題。
x1を真にx2を偽にすればこのCNF論理式は真になるので回答はYes。
3-SAT問題
SAT問題の中で節のリテラル数が高々3つのもの。
3SATがNP完全であることの証明
SATがNP完全であることはCook Levinの定理より自明である。
3SAT問題に関して、リテラルへの値の代入は多項式時間で検証できるため、3SATはNPである。
SATが多項式時間で3SATに変換できるならば3SATがNP完全であるので、これを示す。
以下のようにして3つ以上のリテラルを含むSATの各節を3SATのいくつかの新しい節の連接節に縮小する。
SATの1つの節を例とする
1.対応するSATの節の最初の2つのリテラルと自由変数z1との論理和である3SATの新しい節を作る。
2.SATの節の次のリテラルとz1の否定と自由変数z2の論理和の節を作る。
3.これをSATの節のリテラルが残り2つになるまで繰り返し、最後の2つのリテラルと最後の自由変数の否定で論理和の節を作る。
4.1から3ををSATの各節に対して行い新しい3SAT問題を作成する。
このSAT3への変換は元のSATがm個(m>3)のリテラルを含む場合、変換されたSAT3はm-2の節を持ち、m-3の自由変数を持つ。 したがってこの変換は多項式時間、多項式空間でできる。
次に、この変換を行った際、問題の真偽が変わらないことを示す。
あるSATが充足可能のとき、対応する3SATも充足可能である。
SATはすべての節が同時に真と評価されるときに充足可能である。SATの節が真のとき、少なくとも1つのリテラルは真である。したがって、対応する3SATでは、その真であるリテラルを含む節は真であり、3SARTのその節の自由変数を偽にすることで隣の3CNF節を真にすることができる。よってすべての3CNF節を真にするように変数を変えることができる。
3SATが充足可能なとき、対応するSATも充足可能である。
3SATのすべての節は真になる。これはSATのすべての節に少なくとも1つ真であるリテラルが存在する場合である。SATのある節のすべてのリテラルが偽の場合、3SATの自由変数に関わらず節を真にすることができないため。よってSATの節のリテラルは少なくとも1つ真であり、対応するSAT節を真にする。
, より、3SAT問題はNP完全である。
【JavaScript】MNISTデータベース(バイナリファイル)を扱う
はじめに
JavaScriptでバイナリデータを扱いたい。 MNISTデータベースの教師用画像をJavaScriptのcanvasを用いて表示する。 Qiitaから移行。
MNISTデータセットの入手
よく手書き文字認識に使われるデータベース
http://yann.lecun.com/exdb/mnist/
ここからダウンロードできる。
今回は教師画像データの"train-images-idx3-ubyte.gz"をダウンロードして使う。
Windowsのコマンドプロンプトで
gzip -d train-images-idx3-ubyte.gz
で展開するとtrain-images-idx3-ubyteが出てくる。
上記のサイトに中身のフォーマットが書いてある
[offset] [type] [value] [description]
0000 32 bit integer 0x00000803(2051) magic number
0004 32 bit integer 60000 number of images
0008 32 bit integer 28 number of rows
0012 32 bit integer 28 number of columns
0016 unsigned byte ?? pixel
0017 unsigned byte ?? pixel
........
xxxx unsigned byte ?? pixel
Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black).
HTMLを用意する
ファイルを読み込むためにinputを用意しておく。 今回はcanvasを使うのであらかじめhtmlにcanvasも用意しておく。 bodyは最低限でこんな感じ。
<body> <input type="file" id="imgfile"> <br/> <canvas id="canvas"></canvas> <script type="text/javascript" src="main.js"></script> </body>
バイナリデータを扱いやすく変換する
バイナリファイルを読み込むときに使うのがDataViewオブジェクト
new DataView(buffer [, byteOffset [, byteLength]]) DataView.prototype.getUint8() ビューの開始位置から指定されたバイト単位のオフセットで符号無し8ビット整数値(unsigned byte) を取得します。。 DataView.prototype.getInt32() ビューの開始位置からの指定されたバイト単位のオフセットで符号あり32ビット整数値(long)を取得します。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/DataView
画像の枚数、高さ、幅をフォーマットに従って取得してみる。
var input = document.getElementById("imgfile"); //input要素を取得 input.addEventListener("change", function(event){ //input要素に変更があったら発火 var file = event.target.files; //FileListオブジェクトを取得 var binaryReader = new FileReader(); //FileReaderオブジェクトを生成 binaryReader.readAsArrayBuffer(file[0]); //ファイルをArrayBufferオブジェクトとして格納 binaryReader.onload = function(){ //読み込みが成功したら発火 var dataView = new DataView(binaryReader.result); //DataViewオブジェクトを生成 var number_of_images = dataView.getInt32(4); //画像の枚数を取得 var row = dataView.getInt32(8); //画像の行数(高さ)を取得 var column = dataView.getInt32(12); //画像の列数(幅)を取得 console.log(number_of_images, row, column); //確認用に出力 } }
無事60000 28 28
と出力された。
それでは画像1枚1枚のデータを取得していきたい。
1枚の画像は28x28の784個のunsigned byte(0-255)で構成されるので、
要素が784個の1次元配列を60000個の、[60000, 784]の2次元配列で6万の画像を扱う。
DataViewからその配列に変換する関数を作成した。
var mnistToImageArray = function(dataView, number_of_images, row, column){ var images = []; var offset = 0; for(var i = 0; i < number_of_images; i++){ images.push([]); //画像データを入れる1次元配列を挿入 for(var j = 0; j < row; j++){ for(var k = 0; k < column; k++){ images[i].push(dataView.getUint8(16 + offset)); //Uint8を入れていく offset++; //offsetを次へ } } } return images; }
画像をcanvasに描画する
まずはcanvas、contextを取得してImageDataオブジェクトを作る。 ImageDataとは
ImageData インターフェイスは、
ImageData.data 読取専用 RGBA の順で 0 から 255 の間の整数 (両端の値を含む) を並べたデータを持つ 1 次元配列を表す Uint8ClampedArray です。
canvasを28x28に変えてからImageDataオブジェクトを作る。
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); canvas.width = column; canvas.height = row; var dstData = ctx.createImageData(canvas.width, canvas.height);
作ったImageDataを先ほど1次元配列にした画像データを入れる関数を作る。 1次元配列なので2重ループでのインデックスに注意。 MNISTのデータは0を黒、255を白にしているので注意。
var dataArrayToImageData = function(dataArray, imageData){ //dataArray->独自に変換した画像データ for(var i = 0; i < imageData.height; i++){ for(var j = 0; j < imageData.width; j++){ var idx = i + j * imageData.width; //1次元配列の適したインデックスを指すように変数を作る var idx2 = idx * 4; //ImageData.dataはRGBAの情報があるのでインデックスを4倍する imageData.data[idx2] = 255 - dataArray[idx]; //白黒反転させる imageData.data[idx2 + 1] = 255 - dataArray[idx]; //RGBに同じ値を入れる imageData.data[idx2 + 2] = 255 - dataArray[idx]; imageData.data[idx2 + 3] = 255; //不透明度は最大 } } }
ここまできたら今までのを全部まとめて、ctx.putImageData()でImageDataをcanvasに入れるだけ。 最終的なソースがこれ。
var mnistToImageArray = function(dataView, number_of_images, row, column){ var images = []; var offset = 0; for(var i = 0; i < number_of_images; i++){ images.push([]); //画像データを入れる1次元配列を挿入 for(var j = 0; j < row; j++){ for(var k = 0; k < column; k++){ images[i].push(dataView.getUint8(16 + offset)); //Uint8を入れていく offset++; //offsetを次へ } } } return images; } var dataArrayToImageData = function(dataArray, imageData){ //dataArray->独自に変換した画像データ for(var i = 0; i < imageData.height; i++){ for(var j = 0; j < imageData.width; j++){ var idx = i + j * imageData.width; //1次元配列の適したインデックスを指すように変数を作る var idx2 = idx * 4; //ImageData.dataはRGBAの情報があるのでインデックスを4倍する imageData.data[idx2] = 255 - dataArray[idx]; //白黒反転させる imageData.data[idx2 + 1] = 255 - dataArray[idx]; //RGBに同じ値を入れる imageData.data[idx2 + 2] = 255 - dataArray[idx]; imageData.data[idx2 + 3] = 255; //不透明度は最大 } } } var input = document.getElementById("imgfile"); //input要素を取得 input.addEventListener("change", function(event){ //input要素に変更があったら発火 var file = event.target.files; //FileListオブジェクトを取得 var binaryReader = new FileReader(); //FileReaderオブジェクトを生成 binaryReader.readAsArrayBuffer(file[0]); //ファイルをArrayBufferオブジェクトとして格納 binaryReader.onload = function(){ //読み込みが成功したら発火 var dataView = new DataView(binaryReader.result); //DataViewオブジェクトを生成 var number_of_images = dataView.getInt32(4); //画像の枚数を取得 var row = dataView.getInt32(8); //画像の行数(高さ)を取得 var column = dataView.getInt32(12); //画像の列数(幅)を取得 var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); canvas.width = column; canvas.height = row; var dstData = ctx.createImageData(canvas.width, canvas.height); var images = mnistToImageArray(dataView, number_of_images, row, column); dataArrayToImageData(images[0], dstData); ctx.putImageData(dstData, 0, 0); } }, false);
最後に
Deep Learningを勉強していてMNISTデータベースを使った手書き文字認識というのが最初にでてきたので、やってみようと思った。 Deep Learningの主流はpythonで、pythonでモジュールを使って楽にMINSTデータベースを扱えるらしいが、なんとなくJavaScriptで書いてみることにした。。
【AtCoder】ABC072C解説
時間制限 : 2sec / メモリ制限 : 256MB
配点 : 300 点
問題文 長さ N の整数列 a1,a2,…,aN が与えられます。
各 1≤i≤N に対し、ai に 1 足すか、1 引くか、なにもしないかの三つの操作からどれか一つを選んで行います。
この操作の後、ある整数 X を選んで、ai=X となる i の個数を数えます。
うまく操作を行い、X を選ぶことで、この個数を最大化してください。
制約
1≤N≤105
0≤ai<105(1≤i≤N)
ai は整数
入力
入力は以下の形式で標準入力から与えられる。N a1 a2 .. aN 出力 うまく操作を行い、X を選んだ時の ai=X なる i の個数の最大値を出力せよ。
自分の考え
1降順ソートしてから先頭から見る
2今のai+2までのaiの個数を数える
3aiの連続が途切れる度2を繰り返す
これで2の最大が出力になる。
ちょっと上手く説明できないのでコードで。
n = int(input()) a_n = list(map(int, input().split())) a_n.sort() a_n.reverse() def check(idx): global a_n base = a_n[idx] count = 0 dif = 0 while dif <= 2: idx += 1 count += 1 if(idx == n): return count dif = base - a_n[idx] return count ans = 1 i = 0 c = check(i) tmp = a_n[0] while(i != n): if(tmp != a_n[i]): tmp = a_n[i] c = check(i) if(ans < c): ans = c i += 1 print(ans)
なんとも冗長なコードになってしまった。 ここでコード長最短ACの方のコードを見てみよう。
c=[0]*10**5;input() for i in map(int,input().split()): c[i]+=1 print(max([sum(c[i:i+3]) for i in range(10**5)]))
たった4行である。 入力の最大個数である105の長さの配列を宣言し、入力のそれぞれの値に対応するインデックスにその値がいくつあるのかカウントしている。 最後に3つごとにスライスし、その合計の最大を出力する。 非常に美しいコードだ。
メモ
Pythonでセミコロンを使うと1行に2行分書けることを初めて知った。最初の入力Nは使う必要がないので、最初の行の後ろに書いたのだろう。
Deep Learning入門概略
はじめに
「オライリー・ジャパンのゼロから作るDeep Learning」を読んで忘れないうちに備忘録的にディープラーニングの教師ありの分類問題についてまとめていきます。 隠れ層が1層の2層ニューラルネットワークを数値微分を使って勾配を求めて学習する部分までまとめます。
パーセプトロン
パーセプトロンとはニューラルネットワーク(ディープラーニング)の起源となるアルゴリズム。 複数の入力を受け、1つの出力をする。 出力は0か1だけ、例えば、二つの入力の合計がθ(閾値)以下なら0、それ以外なら1を返す関数。
ニューラルネットワーク
ニューラルネットワークでは複数の入力にそれぞれ重みをかけて、その上にバイアスを足して、活性化関数によって変換したものを出力します。 文字にすると分かりにくいので数式で表すと。
w1, w2は重み、bがバイアス、hが活性化関数です。
これを層にすることでニューラルネットワークを構築します。 入力層、中間層、出力層に分けられて、それぞれにいくつものノードが存在します。上記の入力、出力を繰り返して信号を伝達していきます。
分類問題を学習するには、入力と出力のデータ(教師データ)を用意します。 ニューラルネットワークに入力し、その出力と教師データの正解との誤差を求め、重み、バイアスを調整して、ニューラルネットワークの出力を正解に近づける。 これを繰り返して、分類問題を学習します。
行列
ニューラルネットワークの計算は行列を使ってまとめて行うことができます。
内積の計算を行うので、重みWの行数は入力Xの列数である必要があり、バイアスBは重みの列数と同じ次元である必要があります。
活性化関数
活性化関数が実際にどういった関数か、今回使う活性化関数を紹介します。
シグモイド関数
グラフと書くと分かりますが、0から1の実数を出力する単調増加関数です。
ソフトマックス関数
シグモイド関数と同様に、0から1の実数を出力します。この値は確率として解釈でき、多クラス分類に使うことができます。 例えば出力が(0.1, 0.1, 0.2, 0.6)であれば4番目のクラスy4の確率は60%と言えます。
損失関数
損失関数とは簡単に言えば誤差を求める関数です。
yはニューラルネットワークの出力、tは教師データとします。
2乗和誤差
交差エントロピー誤差
勾配
勾配とは、ある関数のすべての変数の偏微分をベクトルとしてまとめたものです。 関数f(x, y)なら勾配は
です。 損失関数の勾配を求めれば、勾配はその点において、最も変化量の多い方向を指します。 これを用いて、誤差が最も少なくなる方向に重み、バイアスを変更します。 ※勾配はあくまでその点において、極小値、鞍点を探すだけで、必ずその関数の最小値を指すわけではない。
数値微分
勾配を求めるために偏微分を使いたいが、微分はxの小さい変化(限りなく0に近い)によって関数f(x)がどれだけ変化するというものです。
プログラムでは限りなく0に近い値は表せないので、実際に0近い値だけxを変化させて微分を求めることを数値微分と言います。
丸め誤差で省略されない程度に、例えば変化量を0.0001として
のように求めます。
【Python】音声を離散フーリエ変換して周波数帯ごとにビジュアライズする
はじめに
この記事の時点で音声に関してあやふやだったことが多いので改めて書くことにした。今回はwavファイルを読み込んでフーリエ変換し、周波数ごとに振幅を表示したい。
wavファイルを読み込む
import wave import numpy as np #Wave_readオブジェクトとして得る wf = wave.open("440Hz.wav", "rb") #チャンネルの番号、1:モノラル、2:ステレオ channels_no = wf.getnchannels() #サンプルサイズ、2ならバイト? sample_width = wf.getsampwidth() #サンプリング周波数 sampling_frequency = wf.getframerate() #全体のフレーム数 frames = wf.getnframes() #bytesオブジェクトとして最大[引数]フレーム取得する。 buf = wf.readframes(wf.getnframes()) data = np.frombuffer(buf, dtype = "int16") #ステレオだとdataには[左, 右, 左, 右, ...]のように入っているので、スライスして右だけ取り出す。別に左でもいいけどなんとなく。 if(channels_no == 2): data = data[::2] print("Channel No:", channels_no) print("Sample Width:", sample_width) print("Sampling Frequency:", sampling_frequency) print("Frames:", frames) """Standart output Channel No: 1 Sample Width: 2 Sampling Frequency: 44100 Frames: 220500 """
周波数ごとに表示する
import os import time #コンソールクリアのラムダ式 cclear = lambda : os.system('cls' if os.name=='nt' else 'clear') #表示する行数 line = 50 #離散フーリエするデータの幅(1/24秒) delta = int(sampling_frequency / 24) fft_data = [] for i in range(int(len(data) / delta)): #deltaでスライスして高速離散フーリエ変換 fft_data.append(np.fft.fft(data[i * delta:(i + 1) * delta])) #周波数帯ごとに振幅を表示する。 for j in range(line): #まとめる周波数帯をスライスで取得 width = fft_data[i][j * int(delta / line):(j + 1) * int(delta / line)] #振幅の絶対値の平均をとる s = 0 for w in width: s += abs(w) y = s / len(width) #大きすぎるので小さくするため定数で割る length = int(y / 30000) #それでも大きい場合制限する if(length > 100): length = 100 #その周波数帯の先頭と振幅を視覚的に表示する print({0:05d}.format(int(j * delta / line * 24)) + "*" * length)) #0.2秒待機 time.sleep(0.2) #コンソールクリア cclear()
実行結果
440Hzが流れるwavファイルを読み込んだ様子
10kHzが流れるwavファイルを読み込んだ様子
2つ目のfor文の中のdeltaを100とかにすれば100区切りで表示できる。
参考
PythonでWAVファイルを読み込む - 音楽プログラミングの超入門(仮)
22.4. wave — Read and write WAV files — Python 3.6.3 documentation
Blenderで音に合わせてキーフレームを打つ(Blender API)
Blenderで音に合わせてキーフレームを打つ(Blender API)
Pythonで音声ファイル(wav)を読み込んで、それに合わせてBlenderにあるオブジェクトの大きさを変えてアニメーションさせたらきっとかっこいいと思ったので。(あとから知ったのだが、Blenderは音声からキーフレームに変える機能がついているらしい)
Blender APIとは
Blenderの操作をスクリプトから操作することができるもの。Pythonで使うことができる。いつか入門の記事を書きたい。 https://docs.blender.org/api/current/
Pythonからキーフレームを打つ
1フレームに位置のキーフレームを打ちたかったら、下のように書く。
import bpy obj = bpy.context.object # set the keyframe at frame 1 obj.location = 3.0, 4.0, 10.0 obj.keyframe_insert(data_path="location", frame=1)
メソッドの説明
keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group="") Insert a keyframe on the property given, adding fcurves and animation data when necessary.
Parameters:
data_path (string) – path to the property to key, analogous to the fcurve’s data path.
index (int) – array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.
frame (float) – The frame on which the keyframe is inserted, defaulting to the current frame.
group (str) – The name of the group the F-Curve should be added to if it doesn’t exist yet.
options –
Optional flags:
INSERTKEY_NEEDED Only insert keyframes where they’re needed in the relevant F-Curves.
INSERTKEY_VISUAL Insert keyframes based on ‘visual transforms’.
INSERTKEY_XYZ_TO_RGB Color for newly added transformation F-Curves (Location, Rotation, Scale)
and also Color is based on the transform axis.
Returns:
Success of keyframe insertion.
Return type:
boolean
Blenderにオブジェクトを追加する
Blender起動時にあるキューブを使ってもいいが、今回は新しくキューブを作って、それにアニメーションを適用させる。
1行目で生成し、2行目でシーンでアクティブにする。
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0)) obj = bpy.context.scene.objects.active
wavから波形データをアニメーションに移す
以前の記事でやった配列を使ってキーフレームを打っていくだけ。取れるデータは大きいので、スケールの倍率は配列の中の最大値で割って正規化する。今回使った音声データは3分ほどあるので、最初の250フレームだけキーを打った。
import wave import numpy as np import logging file = "絶対パス" wf = wave.open(file, "r") buf = wf.readframes(wf.getnframes()) data = np.frombuffer(buf, dtype = "int16") frame = wf.getnframes() rate = wf.getframerate() vframe = int(rate / 24) vdata = [] for i in range(int(frame / vframe)): vdata.append(data[i * vframe * 2]) bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0)) obj = bpy.context.scene.objects.active vdata_max = max(vdata) for i in range(250): obj.keyframe_insert( data_path='scale', frame=i) tmp = vdata[i] / vdata_max obj.scale = (tmp, tmp, tmp)
実行するとキーフレームが自動的に打たれる。
参考
【C#】ファイルの読み書き
はじめに
ただの簡単なファイルへの書き込み、読み込みのやり方
System.IO.StreamReader, StreamWriterを使う
StreamWriterのコンストラクタの第2引数はtrueで追記、falseで上書き。コンストラクタはいっぱいオーバーロードされてるので詳しくはリファレンスを。
append
Type: System.Boolean
true to append data to the file; false to overwrite the file. If the specified file does not exist, this parameter has no effect, and the constructor creates a new file.
using System.IO; public class Test { static string FILE_NAME = "test.txt"; public static void Main () { using (StreamWriter sw = new StreamWriter(FILE_NAME, false)){ sw.WriteLine("Test"); } if (File.Exists (Application.dataPath + FILE_NAME)) { using (StreamReader sr = File.OpenText (FILE_NAME)) { Console.WriteLine(sr.ReadLine ());//1行 //Console.WriteLine(sr.ReadToEnd ());//全部 } } } }
1行づつ扱いたかったら
while( (line = sr.ReadLine()) != null) { Console.WriteLine(line); }
usingについて
ファイルストリームは開いているときロックされて他からアクセスできないので、閉じる必要がある。基本的に関数の中の変数などが参照されなくなったら自動的にガベージ・コレクションが行われるが、そのタイミングは参照されなくなった時点ではないので、ファイルストリームなどの場合は明示的に解放する必要がある。StreamReaderにはClose()メソッドがあり、使い終わったらClose()すればいいのだが、リソースを解放するためにDispose()というメソッドが実装されている(Close()は破棄するわけではない、詳しく参考を。)。そこで、Dispose()を自動的にやってくれるのがusing構文という訳だ。以下の2つのプログラムは同じことだ。
using (Font font1 = new Font("Arial", 10.0f)) { byte charset = font1.GdiCharSet; }
{ Font font1 = new Font("Arial", 10.0f); try { byte charset = font1.GdiCharSet; } finally { if (font1 != null) ((IDisposable)font1).Dispose(); } }
参考
using Statement (C# Reference) | Microsoft Docs
StreamWriter コンストラクター (String, Boolean) (System.IO)
.NET TIPS ガベージ・コレクタを明示的に動作させるには? - C# VB.NET - @IT
ファイル操作 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C