【第4回】Perlで画像処理 -GIFで2D画像から3D作成-

せっかく、PDLと行列の使い方を覚えたのだから
それを使って何かすれば良かったんだけど忘れてたでござる。

今回はGIFで2D画像を3Dに見せるファイルを作ってみる。
具体的な内容は下記サイトを見てほしい。

2Dなのに飛び出す! 3D環境ゼロでつくる3D写真のつくりかた

簡単に言うと、同じ場所が写っている画像を
視点を少しずらして、その元の画像と視点をずらした画像を
交互に見せることによって3Dっぽく見せるという技術。

というわけで
use strict;
use warnings;
use Imager;
use Image::Size;

my $img_orign = Imager->new;
my $img_depth = Imager->new;
$img_orign->read(file => 'orign.PNG') or die $img_orign->errstr;
$img_depth->read(file => 'depth.PNG') or die $img_depth->errstr;

my ($max_width, $max_height) = imgsize('orign.PNG');
my @set_imgs;
my @set_imgs_right;
my @set_imgs_left;
for (my $i = 0; $i < 2; $i++) {
my $set_img_right = Imager->new;
my $set_img_left = Imager->new;
$set_img_right->read(file => 'orign.PNG') or die $set_img_right->errstr;
$set_img_left->read(file => 'orign.PNG') or die $set_img_left->errstr;

for (my $x = 0; $x < $max_width; $x++) {
for (my $y = 0; $y < $max_height; $y++) {
my $pixel = $img_orign->getpixel(x => $x, y => $y);
my $right_x = $x + $i * 0.5;
my $right_y = $y;
my $left_x = $x - $i * 0.5;
my $left_y = $y;
my $depth_pixel = $img_depth->getpixel(x=> $x, y => $y);
my ($r, $g, $b) = $depth_pixel->rgba();
if ($r >= 255) {
$right_x += $i * 2.5;
$left_x -= $i * 2.5;
}
elsif ($g >= 255) {
$right_x += $i * 2;
$left_x -= $i * 2;
}
elsif ($b >= 255) {
$right_x += $i * 1.5;
$left_x -= $i * 1.5;
}
$set_img_right->setpixel(x => $right_x, y => $right_y, color => $pixel);
$set_img_left->setpixel(x => $left_x, y => $right_y, color => $pixel);
}
}
push @set_imgs_right, $set_img_right;
push @set_imgs_left, $set_img_left;
}

push @set_imgs, @set_imgs_right, @set_imgs_left;

my $save_img = Imager->new;
$save_img->write_multi( {
file => 'save.gif',
gif_delay => 0,
gif_loop => 0,
}, @set_imgs) or die $save_img->errstr;

■元の画像(orign.png)
orign












■奥行き画像(depth.png)
depth












赤が一番手前と考えて
赤 > 緑 > 青 > 色なし

■結果(save.gif)
save












どうですかね?
3Dっぽく見えるかな?
み。。。見えないこともないかorz
(自分で色々試していると段々感覚がわからなくなってきたぞ。。。)

考え方としては、元の画像から1ピクセルずつ
右(または左)にずらして
後は奥行き画像から手前にあるものほど大きく
奥にあるものほど小さくピクセル移動するよう補正をかけているだけ。
なんだけど難しい。
参考にしたサイトのように綺麗にならないしね。
ノイズを消したり、補正する量(箇所)をより細分化すれば
綺麗になるのかな。

【追記】
コメントの案を試してみました。

①赤<緑<青<色なし
手前1












②赤<緑<青<色なし
手前2














如何でしょうか。

※改善はできるので、時間作って試すのはありかも。。。