スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

GIMPで写真を夕方風にする

こんばんは。今日はプログラムは進捗なしです……。

というわけで、今日は写真の加工をしてみたいと思います。
参考にしたのはこちらの記事です。

撮影した写真を夕方風にするというものです。
リンク先ではAdobe社のPhotoshopを使っていますが、持っていないのでGIMPで代用してみたいと思います。

GIMPは高機能なフリーのお絵かきソフトです。
以前紹介したInkscapeがベクトル系(点と線の情報で図形を表現)のソフトであるのに対し、こちらは写真加工などに向いているドロー系のペイントソフトです。
本家はこちら(英語です)。わかりやすい日本語のダウンロード方法のまとめページなども調べればすぐヒットします。

それでは、さっそくこちらの写真を加工してみましょう。



GIMPを開いたら、猫の(ちょっと腹の立つ顔の)イラストが描いてあるところに写真をドラッグ&ドロップします。すると、写真をインポートすることができます。

カラーバランスをいじってみます(あとからレイヤーを複製した方が良かったかもしれないと思いました)。

上のツールバーを「色」→「カラーバランス」の順に選択します。



カラーバランスウィンドウが出てきますので、実際にいろいろいじって調節します。
上のラジオボタンで「シャドウ」を選択するとバックの青空を、「ハイライト」を選択すると雲を、「中間層」を選択すると全体を調節することができます。

まずは「シャドウ」で影と青空の部分を調整します。



うーん。続いて中間層。



微妙ですね。
最後にハイライト。



おっ、確かに参考ブログ通り、イエローに振ると夕焼けっぽくなりますね!

ここでうっかり「OK」を押して処理を確定しなかったためにもう一回同じことをやるはめになりました。
今回の写真の加工の場合は「シャドウ」(青空)→「ハイライト」(雲)→「中間層」(全体のバランスを整える)って流れの方がやりやすかったかもしれません。


なにはともあれ、今度は全体のトーンを暗くします。
若干色調変わってますが気にしないでください。あの瞬間は二度と戻ってこない。

同じく「色」→「トーンカーブ」を選択します。



トーンカーブウィンドウが出てきますので、引っ張って若干暗めに。



ちょっと調節して、できました。



一回目の色調のがよかっt(ry
こうしてちょっと時間を置いてみるとまだぜんぜん青空じゃんよ! と思ったりもしますが、まぁなかなかノスタルジックな雰囲気は醸し出せた感じがするので概ね満足です。



さらにおまけ。

カラーバランスをもう少しイエローに振り、今度はトーンカーブをかなり極端に変更してみます。



すると!




どうでしょう! 完全に爆発です!!
夜中にひとりでテンション上がりました!!
左下の建物がまたいい色に染まって世紀末感を煽ります。



何故か深夜テンションで妙な煽り文句を入れたりしてみました。

まとめとしては、
・色調とトーンカーブをいじると不思議な雰囲気の画像を作れる。
・雲の写真があれば簡単に爆発の画像を作れる。

ゲームの背景やエフェクトにも使えそうですね。
またいろいろ遊んでみたい案件だ!

それでは、今回はこの辺りで。
スポンサーサイト

ffmpegによるmp4形式の動画のキーフレームの設定について

今日はキーフレームのお話をしたいと思います。

動画ファイルのデータ表現について
ご存知の方が多いと思いますが、動画ファイルというものはたくさんの静止画を連続で表示することによって表現されています。ぱらぱらマンガのようなものです。
この静止画の集まり、一枚ずつばらばらに保存していると動画ファイルのサイズがとても大きくなってしまいます。
そこで、静止画を何枚かにまとめ、そのまとまりごとに保存することが多いです。これが圧縮という操作です。
動画を扱う際には、この圧縮方法に気を使ってやらなければいけない場合があります。

キーフレームについて
上で述べたように、動画はいくつかのまとまりに分割されて保存されます。
MPEG形式の動画では、このまとまりの最小単位のことをGOP(Group Of Picture)と呼びます。
そして、GOPの一枚目の動画をキーフレーム(またはイントラフレーム、Iフレーム)と呼びます。
詳しくはこちらをさっくり読んでみてください。
ごちゃごちゃ書いてありますが、要はキーフレームがまとまりのインデックスになってると思ってください。

んで、このキーフレーム、動画の再生点を変えるのに使うんです。
例えば、40秒の動画があるとします。
この動画は、キーフレームが5秒ごとに設定されています。
この動画の再生点を18秒にする場合のイメージはこんな感じです。



このように、インデックスであるキーフレームに移動してから再生したい位置に再生ヘッドを移動させていると考えてください。
再生点の移動(シーク)はキーフレームごとにしかできません。

ここで問題が。
例えば、15秒から再生したい!という場合は簡単です。15秒のキーフレームにぽーんとシークしてそのまま再生を始めることができます。
しかし図のように18秒から再生したい場合、15秒にいったんシークして、その後18秒に再生点が到達したら動画を表示します。
つまり、約3秒程度のタイムラグが発生するわけです。
動画にもよりますが、30秒動画の真ん中あたりを再生したいときに5秒も10秒も待たされたらちょっといらいらしますね。
そこで、このキーフレームをたとえば1秒ごとに挿入してあげます。すると、シークが1秒ごとになり、結果としてタイムラグは1秒以下に抑えられます。

ただ、注意しなければならないのは、このキーフレームを増やすと動画のサイズが大きくなってしまうというデメリットがある点です。
自分の再生環境に合わせて折り合いをつけていきましょう。

GOPの設定方法

以前紹介したffmpegにGOPを設定する方法があるようです。
GOPはオプションで設定できます。

ffmpeg -i 変換元のファイル -g GOPの間隔 変換後のファイル


GOPの間隔はフレームレートによってかわります。
例えば、フレームレート30fps(つまり、1秒間に30枚の画像が表示される)の場合、設定するGOPを300とすれば300枚の画像を1つのまとまりとするので、キーフレームは300÷30となり、10秒ごとにキーフレームが挿入されることになります。
また、同じくフレームレート30fpsでGOPを30に設定した場合、画像30枚ごとにキーフレームが挿入されるので、結果として1秒ごとにキーフレームが設定されることになります。

以上、キーフレームについてでした。
ちょっとまだよくわかってない部分も多いので、修正することもあるかもしれません。
ご参考までに。

それでは、今回はこの辺りで。

Processingを実行したら動作が重かったので修正したときの覚書

Processingで引き続きシステムを作っています。
今回、

マウスで画面上に配置されたボタンをクリックする→テキストエリアに文字列が表示される

というシステムを作ってデモを行っていました。

が、実行してみると何故か挙動がおかしい。
具体的にいうと、一回目にボタンを押したときだけレスポンスが妙に遅い。
二回目以降は迅速なレスポンスが返ってくるのに…。

別のプログラムでサーバーを立て、クライアントとしての動作もさせていたので通信部分の不具合化と思いいろいろ試しましたが直りません。
30分程悩んでいたところ、なんとか原因が究明できました。

ボタンを押したときに文字列を書き込む。ここが問題でした。
一回目にボタンを押したとき、初めて文字を使用することになります。
すなわち、フォントの設定などの処理が初めてボタンが押された瞬間に行われていたようです。
そのため、最初の一回のみ処理が多くなり、まるでフリーズしたかのような挙動になってしまっていたのですね。

setup()の処理の中であらかじめ開始の合図の文字列を表示させておいたところ、ボタンはきちんと動作するようになりました。
同じ現象を再現できたので、サンプルを貼っておきます。
前回のボタンのサンプルの1_1、1_2と同じ素材を使用しています。


PImage button1_1,button1_2;

boolean flag1 = false;

void setup(){
size(400,450);
button1_1 = loadImage("button1_1.png");
button1_2 = loadImage("button1_2.png");
//text("button Released!",100,200); //<---1
image(button1_1,50,50);
}

void draw(){}

void mousePressed(){
if(mouseX >= 50 && mouseX <= 350 && mouseY >= 50 && mouseY <= 150){
flag1 = true;
println("Button Pressed!");
image(button1_2,50,50);
}
}

void mouseReleased(){
if(flag1 == true && mouseX >= 50 && mouseX <= 350 && mouseY >= 50 && mouseY <= 150){
println("Button Released!");
text("button Released!",100,200); //<---2
}
flag1 = false;
image(button1_1,50,50);
}


コメントで1、2と書いてある部分が今回の問題の原因となったコードです。
このまま実行すると、2の部分でボタンを押した一回目の処理が遅くなることがわかります。
そこで、1の部分のコメントアウトを外してみましょう。
setup()の中でフォントの読み込みの処理が行われ、ボタンの動作には影響しなくなります。

通信部分のバグだと思い込んでいたので、目から鱗でした。
フォントの読み込みのタイミングには気をつけましょう。

それでは、今回はこの辺りで。

Processing スライダーとかControlP5のオブジェクトの色を変更するときのメモ

タイトルの通りスライダーの色を変更するとこでちょっと詰まったのでメモ。
参考はこちらのサイト。

以下はすべてControllerInterfaceというインタフェースのメソッドです。
ControllerIntarfaceを実装しているクラスはこれを使うことができます。
公式のリファレンスはこちら(英語)。


setColorBackground(int)

オブジェクトの背景色を設定します。引数はintです(下で詳しく説明しているので合わせて読んでください)。
スライダーの場合は下地の色になります。


setColorForeground(int)

オブジェクトの前面の色(?)を設定します。引数はintです。
スライダーの場合はマウスがスライダーに乗っていない(アクティブでない)ときのスライダーの色になります。


setColorActive(int)

オブジェクトにマウスが乗っているとき(アクティブなとき)の色を設定します。引数はintです。
スライダーの場合はアクティブなときのスライダーの色になります。


色の表現方法について。

これまで、例えば矩形や文字の色などを設定するときは、255階調グレースケールやRGB値などいろいろな方法で色を決定することができました。
ところが、どうやらControlP5のオブジェクトはこれらの方法ではなくint型で設定する必要があるようです(未検証です)。
色情報は32ビットのデータで表現されます。



こんな感じです。RGB形式またはHSV形式を選択でき、デフォルトはRGBです。
なので、32ビットを4ビットごとに区切って8桁の16進数で設定しましょう。
RGB形式については各自でお勉強お願いします。最初の8ビット(=2バイト)は透明度なので注意。

これでスライダーを自分好みの色に設定することができます。

それでは、今日はこの辺りで。

Processingのボタンのサンプルコード

2種類のボタンを作ってみました。
ひとつは押すとへこみ、押し続けて離したときに処理が行われるボタンです。
押したままボタン以外のところにカーソルを持っていって離すと処理はキャンセルされます。
もう一つは押しボタンです。一回クリックするとボタンがへこみ、もう一度クリックすると戻ります。
手を離してもボタンはへこんだままです。

画像には以下のものを用いています。
画像はdataというフォルダをつくって入れてやりましょう。


※ファイル名:button1_1.png



※ファイル名:button1_2.png



※ファイル名:button2_1.png



※ファイル名:button2_2.png


以下のサンプルを作ってみました。

実行してみるとこんな感じになります。








実際に触ってみると、二つのボタンの違いがわかると思います。

PImage button1_1,button1_2;
PImage button2_1,button2_2;

boolean flag1 = false;
boolean flag2 = false;

void setup(){
size(400,450);
button1_1 = loadImage("button1_1.png");
button1_2 = loadImage("button1_2.png");
button2_1 = loadImage("button2_1.png");
button2_2 = loadImage("button2_2.png");

image(button1_1,50,50);
image(button2_1,50,250);
}

void draw(){}

void mousePressed(){
if(mouseX >= 50 && mouseX <= 350 && mouseY >= 50 && mouseY <= 150){
flag1 = true;
println("Button1 Pressed!");
image(button1_2,50,50);
}
}

void mouseReleased(){
if(flag1 == true && mouseX >= 50 && mouseX <= 350 && mouseY >= 50 && mouseY <= 150){
println("Button1 Released!");
}
flag1 = false;
image(button1_1,50,50);
}

void mouseClicked(){
if(mouseX >= 50 && mouseX <= 350 && mouseY >= 250 && mouseY <= 400){
if(flag2 == false){
println("Button2 pushed!");
fill(get(0,0));
noStroke();
rect(50,250,300,150);
image(button2_2,50,250);
flag2 = true;
}else{
println("Button2 unpushed!");
fill(get(0,0));
noStroke();
rect(50,250,300,150);
image(button2_1,50,250);
flag2 = false;
}
}
}


Procesingは、画面に上書きしていくかのように描画を行っています。
そこで入れ替える画像のサイズが違う場合は、mouseClicked()の中の処理のように、一度背景色で画像を塗りつぶしてやってから新しい画像を描画する必要があります。

また時間がありましたら詳しく追記します。

2015/07/08 各関数についてメモ程度に追記しておきます。


1,2行目
PImage

Processingの中で画像を扱うためのクラスです。


9~12行目
loadImage("ファイル名")

PImageクラスの変数に外部から画像を読み込んでいます。
読み込む画像はあらかじめdataファイルの中に置いておきましょう。参考


14,15行目
image(PImage,int,int)

画像を描画します。引数は読み込むPImage、X座標、Y座標です。


40行目
fill(color)

次に描画する図形や文字の色を指定します。引数はグレースケール、RGBなどです。


40行目
get(int,int)

ウィンドウの指定したピクセルの色を取得します。引数はX座標、Y座標です。


41行目
noStroke()

次に描画する図形の枠線を描画しないように設定します。


42行目
rect(int,int,int,int)

矩形を描画します。引数は、矩形の左上の点のX座標、Y座標、矩形の幅、矩形の高さです。




それでは、今日はこの辺りで。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。