はかますたいる!きょろの技的雑記

井上恭輔(@kyoro353)の私的かつ技的な日記です。米国サンフランシスコで暮らすエンジニアです。

Image::Magickによるサムネイル生成高速化

Image::Magickは汎用的な画像処理を行えるという利点があるが、速度的にはあまり早くない。
たとえば大量にアップされる一眼レフなどで撮影した大きなサイズのJPEGからサムネイルを生成するというような状況においては、処理速度がボトルネックになってしまうという問題がある。
ところが、どうやらインスタンス生成時にsizeオプションを指定するだけで処理速度が劇的に向上するらしい、ということを同期のエンジニアrai氏から聞いたので試してみた。

ベンチマーク内容
元画像 : http://photozou.jp/photo/show/228995/18479223
(元画像4272x2848を使用、カメラ小僧Gさんの画像をお借りします)
生成画像: 横160pxに固定し、アスペクト比を維持

サムネイル50枚の生成時間を比較する。

■ 検証コード

#!/usr/bin/perl  
use strict;  
use warnings;  
  
use Benchmark qw(timethese);
use Image::Magick;

timethese(50, {
    im_normal     => 'im_normal(    input_file  => "miko.jpg",
                                    output_file => "out_normal.jpg",
                                    width       => 160,
                                    );',
    im_optional   => 'im_optional(  input_file  => "miko.jpg",
                                    output_file => "out_optional.jpg",
                                    width       => 160,
                                    );',
});

sub im_normal {
    my %param = @_;

    my $input_file  = $param{input_file};
    my $output_file = $param{output_file};
    my $fix_width   = $param{width};

    my $image = Image::Magick->new();
   
    $image->Read($input_file);

    my ($width, $height) = $image->Get('width', 'height');

    my $n_width = $fix_width;
    my $n_height = $height * ($n_width / $width);
   
    $image->Thumbnail( width => $n_width, height => $n_height );
    $image->Write($output_file);
   
    return;
}

sub im_optional {
    my %param = @_;

    my $input_file  = $param{input_file};
    my $output_file = $param{output_file};
    my $fix_width   = $param{width};

    my $image = Image::Magick->new( size => $fix_width.'x'.$fix_width );
   
    $image->Read($input_file);

    my ($width, $height) = $image->Get('width', 'height');

    my $n_width = $fix_width;
    my $n_height = $height * ($n_width / $width);
   
    $image->Thumbnail( width => $n_width, height => $n_height );
    $image->Write($output_file);
   
    return;
}


■ 実行環境
Intel Core2Duo 2.6GHz / Memory 2GB / FreeBSD7.0R


■ 実行結果

%perl benche.pl
Benchmark: timing 50 iterations of im_normal, im_optional...
im_normal: 40 wallclock secs (35.78 usr +  3.70 sys = 39.48 CPU) @  1.27/s (n=50)
im_optional: 10 wallclock secs ( 9.70 usr +  0.28 sys =  9.98 CPU) @  5.01/s (n=50)

早っ!!?
インスタンス生成時に引数を加えるだけで速度4倍です。
出力画像のサイズが決まっている場合はsizeオプションを指定したほうが賢明ですね!!


【追記】
同期のhiroki氏と話していて出た話題で、「size指定をすると作業用キャンバスのサイズが限定されるので早くなるんじゃね?読み込みが高速化するんじゃね?」という意見が出たので$image->Readのみ同条件下でベンチしてみた。

■実行結果

%perl benche.pl 
Benchmark: timing 50 iterations of im_normal, im_optional...
im_normal: 37 wallclock secs (33.87 usr +  3.30 sys = 37.17 CPU) @  1.35/s (n=50)
im_optional:  8 wallclock secs ( 7.70 usr +  0.12 sys =  7.82 CPU) @  6.39/s (n=50)

おおお!やっぱりReadが激速化してる!!
逆に言えば縮小の計算コストってそんなに高くないのかもね(笑)

ミクシィ謹製のオンラインコーヒーメーカー「萌香たん」

あまり多くは語れませんがw

■ミクシィエンジニアブログ
オンラインコーヒーメーカー「萌香たん」とはじめるドキドキ☆コーヒーブレイク
http://alpha.mixi.co.jp/blog/?p=386

f:id:kyoro353:20090228012644p:image

オリジナル壁紙も配布中!!

また、ミクシィ上にはこんなコミュを発見。
見ず知らずの方が作ってくださるとは、非常に嬉しいですね。

【オンラインコーヒーメーカ・萌香】
http://mixi.jp/view_community.pl?id=4087183

音楽の記憶

音楽には記憶が宿るのだということを、最近常々感じる。

ニコニコ動画の登場で、
聞く分にはグレーな感はあるものの、
レンタル屋などの普通の方法ではなかなか手に入りにくい、
往年のゲームやアニメの楽曲を高音質で聞くことができるようになった。


自分にとっての往年とは、まさに高専低学年のとき。


もっとも感受性が豊かで、
もっとも繊細で、
もっとも傷つきやすく、
毎日に感動し、
万事を身体全体で受け止めることができた。


技術力の無さが悔しく、
だけど、きっと努力でどんなものでも作れると頑なに信じ、
ただ我武者羅に、
寝ても覚めてもモノを作っていた日々。


創作行為のみが正義と信じ、進んで睡眠時間を削った。


VisualStudioでコードを書く自分に酔い、
Photoshopに触れていることが楽しく、
LightWaveのショートカットを覚えるのが幸せで
AfterEffectsで作れないものなんて無いと思っていた。


ものづくりが、心から楽しかった。


そんな時、いつもパソコンに向かう僕はヘッドホンをして
ゲームやアニメのサントラをBGMに
日が昇るまで作業を続けた。


今、そのとき共にあった曲を聞き返すたびに、
当時の情景、視界、心が躍る気持ち、セカイ、
そういったものたちと一緒に、
抱いていた夢を思い出す。


そのたびに、
失ったものなど何も無いと自分に嘘を付くたびに、
心が締め付けられるように苦しくなって、
目の奥が熱くなる。


僕はいつから「大人」になってしまったんだろうか。


「すべての創作は感動から生まれる」


この言葉の持つもうひとつの意味がわかった気がする。
感動を、感動で終わらせてはいけないのだ。

プレゼン力はある分野においてはキーボードが叩けるのと同じくらい当たり前のことだと思う。

仕事としてのものづくり、特にプロジェクトにおいては、感性をロジカルに相手に説明できることが重要だと思う。
裏付けるデータがあれば尚良い。
説明が苦手な人がいるのも事実だけど、説明が苦手な人は苦手な人なりの伝え方や進め方があるはずだし、それはそれで重要。
何もみんなが同じプレゼンの舞台に立つ必要なんてないじゃないか。


「下手な説明」は、説明と言う舞台においては「下手な説明」以外の何者でもない。
「面白さ」って相手に伝わって初めて面白さだと思う。
自分の脳内から出せない限り、辛いけど、それは単なるマスターベーションだよ。


出来なくても評価されるのは中学生まで、みんなを最低ラインに揃えるのは小学生まで。
能力主義や成果主義が正義なわけではないし、違う部分もあると思うけれど、せめて頑張ってる人、やりたい人、情熱を持ってる人、そういう熱量が高い人を押さえつけるのは、俺は有益だとは思わない。


社会人になるまで、これって当たり前の事だと思っていた。


もちろん自分への戒めもこめて。

オフィシャルサイト

ついに公式サイトオープンしました!

http://star.garra.jp/star/CI10wtlXxuGTL


ねーよwww


しかしこれ、すごく面白い。
目とか口とかの自動認識はすごくOpenCVについてくる正面顔画像のサンプルを使ってるような気がする。
認識のクセがとても似てる。

それにしても、こういう使い方は上手いなぁ。
ディテールも非常に凝ってて、作りこみがすごい。

前回のハンディーカムといい、最近のウェブ広告なんだかすごく面白いぞ。

SONYのハンディーカム特設サイトでボロボロ泣かされた

SONYのハンディーカムのプロモサイトでボロボロ涙が止まらなくなるくらい泣いた。
Webに泣かされるとは思ってもいなかった。
こんなに感動して泣いた広告は生まれて初めて。
しかも子供も結婚も、それすら彼女もいない自分が号泣した。
(逆にその寂しさを骨の髄から感じているからかも知れないけど)


これは本当にすごい。SONYすごい。


【Cam with me】
http://www.sony.jp/products/Consumer/handycam/camwithme/main.html


たぶん、これが単なる映像だと子供がいない自分は何も感じなかっただろうけど、●RECすることで自分の事のような体験導入感に襲われる。
彼氏ができたあたりで娘が自分の手を離れていく感覚にウッ…っときはじめて、結婚式では涙がこぼれた。
その後は涙がボロボロ止まらない。
ボロボロ泣きながら、必死に●RECを押し続ける自分。
俺は日曜の朝から本当になにやってんだ(笑)


孫ができる未来をフォロワで最後に持ってくるのも秀逸。
映像好きな人、インタラクティブコンテンツが好きな人、「このまま何も変化なく老後を迎えて死んでいくのかな」と将来結婚できるかどうか悩んでる人にはぜひ見てほしいサイト。


1分1秒も無駄にできないな。人生楽しもう。
毎日がスペシャル!!


追記:
どうやら10歳くらいのお子さんのいる知人は全然平気だったらしいとの事で、もう一度考察してみた。
たぶん、このコンテクストで語られるコンテンツは日々の生活に虚無感を感じてる人、子供ほしいなと思ってる人、0〜5歳くらいの子供がいる人にリーチしてる。なぜならキレイ過ぎるストーリーだから。童貞妄想と同じようなものか。
まさに「恋に恋する」系演出と言っても過言ではない。


また、たとえ25年間ハンディーカムを持っていたとしても、こういうコンテンツには現実世界では絶対にならない。実現不可能。
とてもアニメ演出的な表現。良い意味でベタというやつ。


だが、そこにインタラクティブ性を入れたのがとても良い。


そんな日曜日のお昼過。

mono最新の2.2をFreeBSD7にインストールしてみた。

monoはFreeBSDでは昔からなかなか一筋縄ではインストール出来ない事で有名。
VM上のUbuntuでは難なくインストールできたのだけど、やっぱりFreeBSDだと駄目らしい。
最近はmonoに関する情報もネット上に集まってきたので諦めずに少し頑張ってみた。

FreeBSDにmonoを入れた】
http://d.hatena.ne.jp/ak11/20081009

【Mono::FreeBSD
http://www.mono-project.com/Mono:FreeBSD

上記サイトを参考にportsにパッチを当てる

$ wget http://bsd-sharp.googlecode.com/files/mono-merge.tar.gz
$ tar xfz mono-merge.tar.gz
$ cd mono-merge
$ make
# make install
$ rehash
$ mono-merge

次にportsでインストール

$ cd /usr/ports/lang/mono
# make install

とすると

gmake: *** [libgiofam.la] Error 1

エラーを吐いて止まるので

FreeBSD 7.0 で cannot find -lgio-2.0 と言われる件 [FreeBSD]】
http://nakagami.blog.so-net.ne.jp/archive/c35372564-1

こちらを参考にしてglib2を再インストールする

$ cd /usr/ports/devel/glib20
# make deintsall
# make install

気を取り直してもう一度。

$ cd /usr/ports/lang/mono
# make install

キタ━━━━(゜∀゜)━━━━ッ!!
インストールできた!!!!!!!!!(≧▽≦)!!!!!

今までpackageからインストールするしかできなかったmono on FreeBSDですが、今回初めて最新版のコンパイル&インストールに成功しました。
先人の皆様に心から感謝!!

初めて2系を使ったけど、いろいろとびっくりするくらい改善されてる。
動作自体も高速になってる感じ。

インタラクティブシェルも面白い!
が、インテリセンスの無い環境でわざわざC#を選ぶメリットも無いなぁ(笑)

ちなみにシェルではこんなことができる。

%csharp
Mono C# Shell, type "help;" for help

Enter statements below.
csharp> int i;
csharp> for(i=0;i<3;i++){
> Console.WriteLine("Hello, miko!");
> }
Hello, miko!
Hello, miko!
Hello, miko!
csharp>

セカイの狭間

私の通勤はオフラインです。
(地下鉄的意味で)


駅に止まっている間しかリンクを押せないので、つまりは駅数分のページしか読めません。
なんとも切ない。


だけど、オフラインはオフラインでどうしようもないので、実はほっとしたりもします。

世界っていう言葉がある。
私は中学の頃まで、世界ってのは携帯の電波が届くところだと漠然と思っていた。

東京には、思ったより沢山セカイの狭間があるなと感じる今日この頃。

monoからMySQLに接続できたよ!

前回のエントリで書いた「monoからMySQLへの接続」に関しての続報ですが、
手元の環境(FreeBSD7.0+mono1.2.5)でMySQLに接続してデータを読み出すことができました!!


やったね!(≧▽≦)


やはりMySQL Connector/Netのソースが間違っていたみたいです。


【Monoで他のDBも使ってみたよ!(PostgreSQLMySQL編) 】
http://codezine.jp/article/detail/2913?p=4


こちらの記述を元に修正してコンパイルしたところ、問題なく動きました。
今回修正してコンパイルしたmono上での動作確認済みデータドライバのバイナリを配布しますので、興味のある方はご利用ください。
動作は無保証です。問題があった場合は配布を中止しますのであしからず。


MySQL Connector/NET データドライバ修正版(116KB)


GACへの登録はrootになって以下のようにします。

#gacutil -i MySql.Data.dll -package 2.0

今回はサンプルとして以下のようなコードを使用しました。

using System;
using System.Data;
using MySql.Data.MySqlClient;

namespace MySqlExample
{
	public class Select1
	{
		public static void Main(string[] args)
		{
			// 接続文字列
			string constr = "Server=localhost;Database=***;Uid=***;Pwd=***;CharSet=utf8";

			// SQL文字列
			string sstr   = "SELECT user_id, user_name, user_password FROM user;";

			using (MySqlConnection dbcon = new MySqlConnection(constr)) 
			{
				using (MySqlDataAdapter da = new MySqlDataAdapter(sstr, dbcon))
					using (DataTable dt = new DataTable())
					{
						// SELECT実行
						da.Fill(dt);

						foreach (DataRow dr in dt.Rows)
						{
							Console.WriteLine("ID:{0} NAME:{1} PASS:{2}", dr[0], dr[1], dr[2]);
						}
					}
			}
		}
	}
}

コンパイルは.NET Framework2.0用なのでgmcsを使用します。

%gmcs mysql_test.cs -r:System.Data.dll -r:MySql.Data.dll

実行するとこんな感じ

%mono mysql_test.exe 
ID:1 NAME:nagi PASS:pass1
ID:2 NAME:zange PASS:pass2
ID:3 NAME:tsugumi PASS:pass3

これで何かすごいことができるわけではないけど、
なんだか長年の悩みが晴れてすっきり!


今私が生きてる界隈では超絶にマイナーなmono/C# or VB.NETですが、なんとかして陽の目を見せてあげたいな。
がんばろっと。

筑波大学に移動中!

今日は会社の仕事で、筑波大学で開催される就活イベント「JeweL」に参加する予定です。
現在、筑波大学に向けて移動中♪
久々の筑波だー!つくばつくば!

一年ぶりくらいの筑波エクスプレスです。何もかも懐かしい。
ranran!!

イベント中はブースに立ってると思いますので、ご興味のある方はぜひ遊びにきてくださいね。

社会人になって学生時間で動けなくなってからは、なかなか未踏系にも顔出せていなかったので、ACな皆さんや内藤や大澤君にも会えたらいいなぁと妄想中です。

それでは本日はどうぞよろしくお願いします!
がんばってきます!