似顔絵おまけプログラム解説

似顔絵のプログラム解説ページです。

シーザー暗号プログラム

ソースコード
11/17のバージョン

<br />
&lt;script&gt;<br />
// 以下をメモ帳などで書いて(全て半角)、「Omake.html」<br />
// という名前で保存。出来たファイルをダブルクリックし、<br />
// ブラウザで開くと…?何も表示されない時は見直してみよう!<br />
&lt;/script&gt;<br />
&lt;!DOCTYPE html&gt;&lt;html&gt;<br />
&lt;head&gt;&lt;meta charset=&quot;SHIFT-JIS&quot;&gt;&lt;title&gt;Omake&lt;/title&gt;&lt;/head&gt;<br />
&lt;script&gt;<br />
function caesal(val){<br />
    	var result = &#8221;;<br />
    	for(var i = 0; i &lt; val.length; i++)     <br />
            result += String.fromCharCode(val.charCodeAt(i) &#8211; 7);<br />
        return decodeURIComponent(result);<br />
}<br />
var moji1 = &#8216;,L:,?8,@:,L:,?8,HL,L&gt;,I&lt;,I&lt;,L:,?9,@9,L=,?M,?M&#8217;;<br />
var moji2 = &#8216;,L:,?8,?;,L:,?8,@M,L:,?8,HL,L:,?8,HM978=,9M88,9M8&gt;&#8217;;<br />
window.onload = function onLoad() {<br />
    	target = document.getElementById(&quot;ans&quot;);<br />
    	target.innerHTML = caesal(moji1 + moji2);<br />
}<br />
&lt;/script&gt;<br />
&lt;body&gt;&lt;div id=&quot;ans&quot;&gt;&lt;/div&gt;&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p>

11/18のバージョン

<br />
&lt;script&gt;<br />
// 以下をメモ帳などで書いて(全て半角)、「Omake.html」<br />
// という名前で保存。出来たファイルをダブルクリックし、<br />
// ブラウザで開くと…?何も表示されない時は見直してみよう!<br />
&lt;/script&gt;<br />
&lt;!DOCTYPE html&gt;&lt;html&gt;<br />
&lt;head&gt;&lt;meta charset=&quot;SHIFT-JIS&quot;&gt;&lt;title&gt;Omake&lt;/title&gt;&lt;/head&gt;<br />
&lt;script&gt;<br />
function caesal(val){<br />
    	var result = &#8221;;<br />
    	for(var i = 0; i &lt; val.length; i++)<br />
            result += String.fromCharCode(val.charCodeAt(i) &#8211; 8);<br />
        return decodeURIComponent(result);<br />
}<br />
var moji1 = &#8216;-M;-@9-A;-M;-@9-IM-M?-J=-J=-M;-@:-A:-M&gt;-@N-@N&#8217;;<br />
var moji2 = &#8216;-M;-@9-@&lt;-M;-@9-AN-M;-@9-IM-M;-@9-IN:89&gt;-:N99-:N9@&#8217;;<br />
window.onload = function onLoad() {<br />
    	target = document.getElementById(&quot;ans&quot;);<br />
    	target.innerHTML = caesal(moji1 + moji2);<br />
}<br />
&lt;/script&gt;<br />
&lt;body&gt;&lt;div id=&quot;ans&quot;&gt;&lt;/div&gt;&lt;/body&gt;<br />
&lt;/html&gt;<br />

11/19のバージョン

<br />
&lt;script&gt;<br />
// 以下をメモ帳などで書いて(全て半角)、「Omake.html」<br />
// という名前で保存。出来たファイルをダブルクリックし、<br />
// ブラウザで開くと…?何も表示されない時は見直してみよう!<br />
&lt;/script&gt;<br />
&lt;!DOCTYPE html&gt;&lt;html&gt;<br />
&lt;head&gt;&lt;meta charset=&quot;SHIFT-JIS&quot;&gt;&lt;title&gt;Omake&lt;/title&gt;&lt;/head&gt;<br />
&lt;script&gt;<br />
function caesal(val){<br />
    	var result = &#8221;;<br />
    	for(var i = 0; i &lt; val.length; i++)<br />
            result += String.fromCharCode(val.charCodeAt(i) &#8211; 9);<br />
    	return decodeURIComponent(result);<br />
}<br />
var moji1 = &#8216;.N&lt;.A:.B&lt;.N&lt;.A:.JN.N@.K&gt;.K&gt;.N&lt;.A;.B;.N?.AO.AO&#8217;;<br />
var moji2 = &#8216;.N&lt;.A:.A=.N&lt;.A:.BO.N&lt;.A:.JN.N&lt;.A:.JO;9:?.;O::.;O:B&#8217;;<br />
window.onload = function onLoad() {<br />
    	target = document.getElementById(&quot;ans&quot;);<br />
    	target.innerHTML = caesal(moji1 + moji2);<br />
}<br />
&lt;/script&gt;<br />
&lt;body&gt;&lt;div id=&quot;ans&quot;&gt;&lt;/div&gt;&lt;/body&gt;<br />
&lt;/html&gt;<br />

11/20のバージョン

<br />
&lt;script&gt;<br />
// 以下をメモ帳などで書いて(全て半角)、「Omake.html」<br />
// という名前で保存。出来たファイルをダブルクリックし、<br />
// ブラウザで開くと…?何も表示されない時は見直してみよう!<br />
&lt;/script&gt;<br />
&lt;!DOCTYPE html&gt;&lt;html&gt;<br />
&lt;head&gt;&lt;meta charset=&quot;SHIFT-JIS&quot;&gt;&lt;title&gt;Omake&lt;/title&gt;&lt;/head&gt;<br />
&lt;script&gt;<br />
function caesal(val){<br />
    	var result = &#8221;;<br />
    	for(var i = 0; i &lt; val.length; i++)<br />
            result += String.fromCharCode(val.charCodeAt(i) &#8211; 2);<br />
    	return decodeURIComponent(result);<br />
}<br />
var moji1 = &quot;&#8217;G5&#8242;:3&#8242;;5&#8217;G5&#8242;:3&#8217;CG&#8217;G9&#8217;D7&#8217;D7&#8217;G5&#8242;:4&#8242;;4&#8217;G8&#8242;:H&#8217;:H&quot;;<br />
var moji2 = &quot;&#8217;G5&#8242;:3&#8242;:6&#8217;G5&#8242;:3&#8242;;H&#8217;G5&#8242;:3&#8217;CG&#8217;G5&#8242;:3&#8217;CH4238&#8217;4H33&#8217;4H42&quot;;<br />
window.onload = function onLoad() {<br />
    	target = document.getElementById(&quot;ans&quot;);<br />
    	target.innerHTML = caesal(moji1 + moji2);<br />
}<br />
&lt;/script&gt;<br />
&lt;body&gt;&lt;div id=&quot;ans&quot;&gt;&lt;/div&gt;&lt;/body&gt;<br />
&lt;/html&gt;<br />

上記のプログラムは主にWebページに使用されているJavaScriptとhtmlによって書かれたスクリプトです。メモ帳などで書いてブラウザで表示できるため、パソコンさえあれば特別な準備は特に必要ありません。

<br />
function caesal(val){<br />
        var result = &#039;&#039;;<br />
        for(var i = 0; i &lt; val.length; i++)<br />
            result += String.fromCharCode(val.charCodeAt(i) - 2);<br />
        return decodeURIComponent(result);<br />
}<br />

ここでやっていることは非常に簡単で、シーザー暗号の解読を行って画面に表示するだけです。シーザー暗号というのはkeyの値だけ文字をずらすというシンプルな暗号(例えばkey = 2なら「あいうえお」は「うえおかき」になり、key = 3なら「えおかきく」になる)で、この処理をfunction caesal内で行っています。Javascriptの基本事項については割愛しますが、ここでは処理をすべき文字列varを1文字ずつ見て、String.fromCharCodeで元の文字(正確には文字コード)を復号しているだけです。文字コードというのは、コンピュータが様々な文字を扱うために、各文字に割り振られた番号のようなものであり、decodeURIComponentを使うとその文字コードから我々が普段使っている文字に置き換えることが出来ます。

<br />
&lt;script&gt;<br />
var moji1 = &quot;&#039;G5&#039;:3&#039;;5&#039;G5&#039;:3&#039;CG&#039;G9&#039;D7&#039;D7&#039;G5&#039;:4&#039;;4&#039;G8&#039;:H&#039;:H&quot;;<br />
var moji2 = &quot;&#039;G5&#039;:3&#039;:6&#039;G5&#039;:3&#039;;H&#039;G5&#039;:3&#039;CG&#039;G5&#039;:3&#039;CH4238&#039;4H33&#039;4H42&quot;;<br />
window.onload = function onLoad() {<br />
        target = document.getElementById(&quot;ans&quot;);<br />
        target.innerHTML = caesal(moji1 + moji2);<br />
}<br />
&lt;/script&gt;<br />
&lt;body&gt;&lt;div id=&quot;ans&quot;&gt;&lt;/div&gt;&lt;/body&gt;<br />

ここでは表示の際の処理が記述されています。ここではページ読み込み時に暗号化されている文字列moji1とmoji2を復号化し、それを表示させています。なお、moji1とmoji2は分ける必要は無いですが、紙面の都合と見やすさからこのようにしています。また、moji1とmoji2を宣言している部分において、文字列はシングルクオーテーション(‘)またはダブルクォーテーション(“)で囲む必要があり、今回のプログラムではシングルクオーテーションで囲みましたが、11/20の文字列にはシングルクオーテーションが含まれているので、この日だけ文字列をダブルクォーテーションで囲っています。

なお、シーザー暗号の復号化のコードは以下のサイトのものを参考にしました。
http://bulldra.hatenablog.com/entry/caesar-crypt

GMA

Rubyの足し算ハック

ソースコード

<br />
#<br />
#整数の足し算をハックし常に1を余計に加算するプログラム(Ruby)<br />
#</p>
<p>class Fixnum<br />
  alias_method :old_plus, :+<br />
  def +(other)<br />
    self.old_plus(other).old_plus(1)<br />
  end<br />
end</p>
<p>def assert(e)<br />
  raise &quot;error!!&quot; unless e<br />
end</p>
<p>assert(1 + 2 == 4)<br />
assert(2 ++++++++++++++++++++++++ 5 == 8)<br />

Ruby では 1 + 2 のような記号もメソッドとして定義されています。1 + 2 はインタプリタに 1.+(2) と解釈され、1 のクラスの + メソッドに引数 2 が与えられて呼び出されます。メソッド名が記号なだけで、動作は普通のメソッドを呼び出したときと何ら変わりません。
また、Ruby ではメソッドに別名をつけることができます。メソッドに別名をつけ、もとのメソッド名と同名のメソッドを再定義すると、外からのメソッド呼び出しでは新しく定義したほうの処理が実行されるため、メソッドの中身を書き換えることができます。これをアラウンドエイリアスといったりします。

ではコードを見ていきましょう。

<br />
class Fixnum<br />

今回は整数の足し算をハックしたいので、整数のクラスである Fixnum を書き換えます。Ruby ではクラス定義も実行時に自由に書き換えることができます。文法は普通のクラス定義と同じです。このようにクラスの定義を再度開くことをオープンクラスといったりします。

<br />
alias_method :old_plus, :+<br />

ここで + メソッドに old_plus という別名をつけました。まだこの時点では 1 + 2 は通常通り実行されますし、1.old_plus(2) としても 3 が返ってくるはずです。

<br />
def +(other)<br />
  self.old_plus(other).old_plus(1)<br />
end<br />

ここで + メソッドを再定義しています。+ メソッドの中ではもとの + メソッドを呼び出したいので、加算は old_plus メソッドを使う必要があります。最後に .old_plus(1) をつけることで、常に 1 がたされることになります。

<br />
def assert(e)<br />
  raise &quot;error!!&quot; unless e<br />
end</p>
<p>assert(1 + 2 == 4)<br />

あとは 1 + 2 が 4 になるよ、と書いてあるだけです。

<br />
assert(2 ++++++++++++++++++++++++ 5 == 8)<br />

これはなんとなく試したら実行できちゃって驚いたのですが、+ 単項演算子がたくさん呼ばれているのだと思います。+ 単項演算子は常に self を返します。つまり、+5 というコードは単に 5 を返します。よってたくさんついている + は単に無視され、最終的に 2 + 5 が実行されるため、実行結果は 8 になります。
ちなみに + 単項演算子は +@ メソッドとして定義されているので、そちらを書き換えれば +5 の結果を 6 にすることもできるはずです。

Ruby ではユーザーがクラス定義を自由に書き換えることができますが、それはプログラム全体の動作を書き換えてしまい、奇妙なバグを引き起こすことがあります。こういったメタプログラミングを行う際は十分注意しましょう。

kyosuke

OpenCLによる画像ぼかし

ソースコード

<br />
//=========================================<br />
// OpenCLによる画像ぼかし<br />
//=========================================<br />
__kernel void Smoothing(<br />
    __constant float4 *Input,<br />
    __constant int *width,<br />
    __global float4 *Result<br />
){<br />
    int x = get_global_id(0);<br />
    int y = get_global_id(1);<br />
    int w = width[0];<br />
    float4 tmp;</p>
<p>    tmp = Input[x + w*y];<br />
    if((x&lt;w-1)&amp;&amp;(y&lt;w-1)) tmp += Input[(x+1)+w*(y+1)];<br />
    if(x&lt;w-1) tmp += Input[(x+1)+w*y];<br />
    if((x&lt;w-1)&amp;&amp;(y&gt;0)) tmp += Input[(x+1)+w*(y-1)];<br />
    if(y&lt;w-1) tmp += Input[x+w*(y+1)];<br />
    if(y&gt;0) tmp += Input[x+w*(y-1)];<br />
    if((x&gt;0)&amp;&amp;y&lt;w-1) tmp += Input[(x-1)+w*(y+1)];<br />
    if(x&gt;0) tmp += Input[(x-1)+w*y];<br />
    if((x&gt;0)&amp;&amp;(y&gt;0)) tmp += Input[(x-1)+w*(y-1)];<br />
    Result[x+w*y] = tmp / 9;<br />
}<br />

GPUを使って画像をぼかすためのコードです.
画像をぼかした状態というのは, たとえば普段眼鏡やコンタクトレンズを使っている人は裸眼の状態, カメラでいうならピントが合っていない状態に近いです. 最近のカメラはオートフォーカスが多いのでピンボケの状態をあまり体験することはないかもしれませんね. あるいは最近のスマートフォンのカメラでも, 被写体がカメラに近すぎるとボケるので, ピンボケの経験はあるかもしれません. (ピンボケってもう死語なのだろうか)

GPUとCPUでは得意な仕事が違います. ざっくりいえば, GPUはグラフィック関係の仕事が得意です. ネットゲームなどでグラボの性能が云々といっているのはGPUのことです. ゲームではGPUの性能がいいと画質が上がったりします. 逆にGPUの性能が低いと, 映像がカクカクします.

話を戻して画像のぼかしについて. 画像をぼかして何が嬉しいのかというと, ノイズを軽減できるという点です. 画像のノイズというのは、例えば壁の汚れだったり、カメラのレンズについた塵などです.
画像解析に限らず、情報処理で大切なことは必要な情報の抽出です. ノイズは不要な情報で、必要なのは被写体の情報です.
塵や汚れなどの細かいノイズはぼかすことによって消え, 大きな被写体は少しくらいぼけても問題ないので, これによって必要な情報のみを残すことができます. このような処理をフィルターと言います.

画像のぼかしはGPU用のコードの中でも簡単な例です. これを機に皆さんも並列沼にはまりましょう.

Bolzman