2010年5月26日水曜日

[Ruby]Gruffを使ってS字トーンカーブを描いてみた

画像処理のプログラミングなどをやっていると数学的な関数を使って値を生成するということがよくあります。

例えば画像のコントラストを変更する処理では、ピクセルの輝度にたいしてどの程度「強い」コントラストを作るか係数を設定して数学的に関数化します。

PhotoshopやGimpなどでコントラストを調整するときに利用するトーンカーブというのはこの関数をグラフ化したものですよね。


傾きが急であれば黒と白が強調されたコントラストが強い画像、ということになります。


このS字トーンカーブを画像で生成するスクリプトを書けば、どういう係数を設定すればどういうカーブを描くか視覚的に判断出来るということで、ちょっと調べてみました。

とりあえずRubyでグラフ画像生成までやってみることに。



コントラストやトーンカーブはこちらの記事が参考になりました。
http://blog.goo.ne.jp/souichi-kikaizikake/e/9c633489d8e5f09c79d70722c6c86635



0~255の輝度値に対して変換する式は下のようになります。 (式の意味はシグモイド関数で検索してみて下さい )
# e => 係数
# i => 輝度値

e = ARGV[0].to_f * 10
256.times do |i|
  v = 255 / (1 + (e ** ((3.5 / 100) * (-i + 127))))
  p v
end
tonecurve.rbという名前で保存して実行してみます。

$ ruby tonecurve.rb 0.5

0.0886149353083345
0.0943479462700696
0.100451712597905
0.10695191619086
...
254.899548287402
254.9056205373
254.911385064692
254.91676982554
数字が256個だーっと生成されます。
これだけだと傾き具合などを把握するのが困難なのでグラフ化します。


幸いrubyには優れたグラフ生成用のgemが用意されているのでそれを活用します。

グラフ生成はGruffを利用することに。
(RMagickのインストールなどがやや面倒だけどオススメです。)


生成された数値を配列に格納して渡すだけでキレイなグラフを作ってくれます。

require 'rubygems'
require 'gruff'

contrast = ARGV[0].to_f

e = 10.0 * contrast
x = 3.5
values = []

256.times do |i|
  values << 255 / (1 + (e ** ((x / 100) * (-i + 127))))
end

g = Gruff::Line.new
g.title = "tonecurve"

g.data("tone (#{e})", values)
g.write('tonecurve.png')

比較のためにグラフを3つ並べてみます。

require 'rubygems'
require 'gruff'

contrast = ARGV[0].to_f

e1 = 10.0 * contrast
e2 = p1 * 0.5
e3 = p1 * 1.5

values1 = []
values2 = []
values3 = []

x = 3.5

256.times do |i|
  values1 << 255 / (1 + (e1 ** ((x / 100) * (-i + 127))))
  values2 << 255 / (1 + (e2 ** ((x / 100) * (-i + 127))))
  values3 << 255 / (1 + (e3 ** ((x / 100) * (-i + 127))))
end


g = Gruff::Line.new
g.title = "tonecurve contrast=#{contrast}"

g.data("tone1 (#{e1})", values1)
g.data("tone2 (#{e2})", values2)
g.data("tone2 (#{e3})", values3)

g.write('tonecurve.png')

視覚化することではっきり傾きが確認できます。
これで係数やゲインの調節がしやすくなりました。

2010年5月21日金曜日

[iOS] BinaryCamera - をリリースしました

iPhoneアプリをリリースしたので紹介します。


BinaryCamera (App Store)

BinaryCameraは印象的な白黒写真が撮影できるアプリです。
面倒な設定は一切不要で撮影した画像に自動的にエフェクトをほどこします。





どうでしょうか?
上がオリジナルの画像で下がエフェクト(バイナリゼーション)をほどこした画像です。


BinaryCameraには複数のエフェクト機能が搭載されています。



バイナリゼーションに背景色を指定


二重閾値バイナリゼーション


ポスタリゼーション







iPhone内臓のカメラで撮影した画像だけでなく、写真アルバムの画像も利用できるのでiPod touchでもご利用いただけます。





エフェクトの種類や背景色に制限があるLite版もあります。こちらは無料ですのでお気軽にどうぞお試し下さい。

2010年5月12日水曜日

"Available on the App Store"アイコンの入手法メモ

iPhoneアプリを開発してappleの審査も通ったら宣伝したくなりますよね。
自分が開発者じゃなくても面白いアプリをみつけたらブログの中で紹介したくなることもあります。

で、アプリのサポートページとかアプリ紹介ブログなどで見かけるあのアイコン(バッヂ) (右のやつ) を使いたいと思い、いろいろ探して公式のものをやっと見つけました。


App Store Resource Center | Marketing Resources

http://developer.apple.com/iphone/appstore/marketing.html


上のページの
Available on the App Store logo artwork~ をクリックするとダウンロードできます。



Available on the App Storeの文言は、今のところ 英語 ドイツ語 フランス語 オランダ語 イタリア語 ロシア語 スペイン語が用意されているようです。


ダウンロードしたファイルを解凍するとpsdファイルが入っているのでそれを加工して使います。

(psdファイルいらないよという方 Google画像検索すれば簡単にpngやjpgファイルが見つかりますよ。)



加工するといっても好き放題できるわけではなく、高さは40px以上じゃなきゃダメとか色々規定があります。


ガイドライン:

App Marketing and Identity Guidelines for Developers

http://devimages.apple.com/iphone/artwork/guidelines0609.pdf

2010年5月9日日曜日

[iOS] UIActivityIndicatorViewでハマった件

UIKitにはUI用の便利なクラスが色々あって、インジケータ(ぐるぐる画像)を表示できるUIActivityIndicatorViewクラスというのが提供されています。

時間のかかる処理を行っている間アプリに何の反応もないと、ユーザーにはアプリがちゃんと動いているのかどうか分かりません。
インジケータは「処理してますよ〜」というサインをユーザーに送ることができるのでけっこう重要です。



UIActivityIndicatorViewを使えば簡単にインジケータを扱えるんだろうなあとタカをくくっていたらちょっとハマったのでメモしておきます。




巷の解説書などによると基本的には下のような流れでUIActivityIndicatorViewを利用します。


まず、オブジェクトを初期化
UIActivityIndicatorView  *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
フレームをセット
indicator.frame = CGRectMake((100.0, 100.0, 50.0, 50.0);
親Viewに追加
[self.view addSubview:indicator];
startAnimatingメソッドを呼び出せばインジケーターが表示される。
[indicator startAnimating];
stopAnimatingメソッドを呼び出せばインジケーターが隠れる。
[indicator stopAnimating];



ところが startAnimating  stopAnimating  を同じスレッド内で実行してもインジケータがうまく切り替わりません。



ようするに
- (void)doSomething {
    ...
    [indicator startAnimating];

    // なにか重い処理を実行...

    [indicator stopAnimating];
}
こんな感じであるメソッド内でstartAnimatingとstopAnimatingを実行してもきちんとインジケータが隠れてくれません!
(出っぱなしになる)

どうやらstopAnimatingはstartAnimatingとは別スレッドで呼び出さなければならないらしいのです。


幸いNSObjectクラスにはperformSelectorInBackground:withObject:というメソッドが用意されているので、それを利用すれば簡単に別スレッドで何らかの処理をすることができます。



そんなわけでサンプルコードはこちら。
- (void)loadView {
    ...
    // 初期化したオブジェクトをインスタンス変数に追加しておく
    self.indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

    indicator.frame = CGRectMake((100.0, 100.0, 50.0, 50.0);
    
    [self.view addSubview:indicator];
}


- (void)doSomething {
    [self.indicator startAnimating];
    [self performSelectorInBackground:@selector(doInBackground) withObject:nil];
}

- (void)doInBackground {
    // 別スレッドで実行するメソッドではNSAutoreleasePoolを使わなければならない
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];

    // なにか重い処理を実行
    ...
    [self.indicator stopAnimating];

    [pool drain];
}

基本的にはこれでインジケータの表示/非表示の切り替えができるようになります。