2009-06-25[n年前へ]
■Mathematicaで発色シミュレーションをオブジェクト風記述にするライブラリ
以前作った、「分光スペクトル・色処理用のMathematicaライブラリ(関数群)」を利用して、「Mathematicaで発色シミュレーションをオブジェクト風記述にするライブラリ」を作りました。前回書いたように、三次元構造の中で反射・屈折・散乱を行う「光」のスペクトルが、どのように変化していったかを知ることができます。
ライブラリは、Imagearts.2.5.nb(3.7MB)として、サイト上にアップロードしてあります。このファイルには、関数・オブジェクト定義に加え、いくつかのサンプルが入っています。
たとえば、「4層構成の物質(Layer)があり、それらの層はすべて透明だけれども、その中間層2層の散乱度合いを変えた場合」のシミュレーションを複数条件下でしたければ、下記のようなコードを書けばOKということになります。
layers[sc_] := (z = #[[3]]; Piecewise[{ {{1, 0,Spector[new][set,transparentFilter]}, z > 1}, {{1, sc,Spector[new][set, transparentFilter]}, 1 >= z && z > 0.5}, {{1, sc,Spector[new][set, transparentFilter]}, 0.5 >= z && z > 0}, {{1, 0,Spector[new][set, transparentFilter]}, 0 >= z} } ]) &;
Table[Light[new][in,Layer[new][set,layers[i]]][showTrace], {i,0,1,0.1}]
ここでは、最初に層構成を純関数として定義し、その純関数を使い、条件を変えたオブジェクトをTableで作成し・計算を行っています。
なお、現状のライブラリは、表面形状は水平平滑に限る、という単純なコードになっています。表面凹凸対応は、また気が向いた(近い)時期にしてみよう、と思います。
2009-10-26[n年前へ]
■「エクセル」と「無名関数」
ふと、エクセルほど無名関数(Mathematicaでいうところの純関数)を使っている開発環境はないのではな いか、と考えた(妄想ともいう)。もちろん、エクセルでも関数を定義したり、記述式を定義したりすることができる。しかし、実際にエクセルを使う状況を考えてみれば、「セルに処理を書き入れ(まく)り」「その処理記述に名前を付けたりはしないまま・コピペしまくり、使い回す」ことが多いと思う。これは、「エクセルが配列ベースの無名関数志向開発環境だ」と言えるのではないか、などと考えてみたのである。
たまに、Rubyでデータ処理し、その結果をエクセルで眺めることがある。そんな時、Rubyとエクセルの組み合せワザのようなことをすることもある。それは、たとえば、こんな具合のコードだ。
d=[] 10.times{d<<'=2*RC[1]'} d<<ARGV[0] puts d.join(',')'=2*RC[1]'の部分は、エクセルの関数である。そして、それ以外の部分はRubyの関数だ。RC[1]は「自分の右のセル」を指すので、次(右)のセルの2倍という関数である。たいていのデータは、左から右(あるいは上から下)に読み込んでいくので、この例の場合、次(未来)の値を使って演算をしていることが面白い、と感じたりする。
それでは、このRubyスクリプトをm.rbと名付け、
ruby m.rb > m.csvとして、m.csvを作成する。そして、そのcsvファイルを(セル表示名ををR1C1形式にした)エクセルで開くとデータ列ができあがる、ということになる。上の例であれば、下のような数値が入ったエクセルシートができあがる。
512 256 128 64 32 16 8 4 2 1
この例のような、複数言語を組み合わせた「闇鍋(やみなべ)ごった煮プログラミング」を上手く活用することはできないだろうか。…そういうことをよく考えるのだけれど、なかなか良いアイデアが思いつかない。何か、面白い位置づけ・適切な使い方がないものだろうか。
2012-04-03[n年前へ]
■「ウォーリーを探す出す」多重解像度解析コードを書いてみる!?
「ウォーリーを探し出す」Mathematica コードがとても面白く・参考になりました。そして、もしも「ウォーリーを探し出す」コードを書こうとしたならば、自分ならどんな風に書くだろう?と考えました。…そこで、試しに、書いてみることにしました。
まずは、画像を読み込みます。
waldo=Import["hoge"]そして、ウォーリーを見つけるには、「やはり、赤白シャツを頼りにすべし」というわけで、赤白模様を検出するための単チャンネルを作成します。ここで、2{1,-1,-1}.#&は、R-G-Bを計算する純(無名)関数です(Stack Over Flow のコードと同処理です。カスタマイズできるように純関数にしています)。
red=ImageApply[2{1,-1,-1}.#&,waldo]次は、ウォーリーを探す部分です。Stack Over Flow で書かれていたコードは「横方向の赤白線の上エッジ検出」を行い、「強いエッジがある部分にウォーリーがいる」という推定を行います。
しかし、その推定では、「ウォーリーが着ているシャツは、赤白横線が何本も入っている」とか「その赤白横線は、胴の形に添った形状をしている」といった情報は用いられていません。
そこで、「胴の形をした赤白横線模様」を作り、さらにその「模様」を用いた多重解像度解析(ウォーリーの大きさは未知ですから)をすることによりウォーリーの位置を推定する、というコードを書いてみました。
mask=Fold[ImageAdd,#[[1]],Rest[#]]&@Table[このコードでは、多重解像度解析を行った上で、ありとあらゆる解像度、すなわち、ありとあらゆる大きさのウォーリーがいる(だろう)位置を、一枚のマスク画像へと焼き付けます。
h=a;w=Floor[h/2];
corr = ImageApply[ 4 Abs[# - .5] &,
ImageCorrelate[red,
Image@ Table[Cos@y, {y, 1, 6 Pi, 6 Pi/h}, {h}],
NormalizedSquaredEuclideanDistance ]];
ImageApply[ #/(30 - 5) &,
Dilation[ImageApply[ If[# > .8, 1, 0] &, corr],
ConstantArray[1, 4 {h, w}]] ] , {a, 5, 30}]
そして、焼き付けた(推定した)「ウォーリーが立っている位置のマスク画像」を用いて、原画像からウォーリーを浮き上がらせてみます。それが、以下の(Stack Over Flowそのままの)最後のコードです。
ImageMultiply[waldo,
ImageAdd[ColorConvert[mask, "GrayLevel"], .5]]
試しに、「ウォーリーをさがすとはどういうことか」で使われていたサンプル画像に処理をかけてみると、次のようになります。これが、「ウォーリーを探す出す」多重解像度解析コードです!?
赤白模様の「壁」などにマッチしないようにしたい場合のために、下記のようなフィルタリングを加えると良いかもしれません(今回はコードを短くするために割愛しました)。
corr2 = ImageApply[ 4 Abs[# - .5] &,
ImageCorrelate[corr,
Image@ Table[
If[x^2 + y^2 < h, 1, 0], {y, -h, h}, {x, -h, h}],
NormalizedSquaredEuclideanDistance ] ];