## 自己紹介
- 仕事: 組み込み系
- Twitter: @techno_neko
- 所属: Hokkaido.pm
## 作った!
- https://github.com/techno-cat/p5-Imager-LineTrace
## Imager::LineTraceとは?
- 画像中のラインをトレースする
- 結果は頂点座標
- 閉じた図形も判別可
## 用意した画像
![用意した画像](./image/1-1.png "1-1")
※実際は、64x64の大きさ
## 用意した画像
- 黒い線が足場
- 緑がスタート
- 赤がゴール
## トレースする
``` perl
my $figures_ref = Imager::LineTrace::trace( file => $path );
```
## 緑と赤について
- 実装上、R,G,Bのいずれかをトレースする
- 緑: #00FF00
- 赤: #FF0000
- 白: #FFFFFF(背景色)
## 緑の要素だけに着目すると?
- 緑: 0xFF
- 白: 0xFF(背景色)
## これじゃ、トレースできない!
緑の点をトレースするのに、
赤(or 青)の要素をトレースするのはおかしい!
## 背景を黒にする
![黒背景の画像](./image/1-1_black.png "1-1")
※実際は、64x64の大きさ
## トレースする
``` perl
my $figures_ref = Imager::LineTrace::trace( file => $path, ignore => 0 );
```
"ignore"で背景色を指定する
## 座標のダンプ
``` perl
my $i = 0;
foreach my $figure (@{$figures_ref}) {
print "-------- [", $i++, "] --------", "\n";
print "type :", $figure->{type}, "\n";
print "trace_value : ", sprintf("0x%06X", $figure->{value}), "\n";
print "is_closed : ", $figure->{is_closed}, "\n";
foreach my $p (@{$figure->{points}}) {
printf( "(%2d,%2d)\n", $p->[0], $p->[1] );
}
}
```
## 緑の要素でトレースする
``` perl
my $figures_ref = Imager::LineTrace::trace( file => $path, channels => [1], ignore => 0 );
```
- "channels"で指定する(0:R, 1:G, 2:B, 3:Alpha)
## 緑の要素でトレースする
- 実は問題が残っている
- 白のラインもトレースされちゃう
- これは厳しい・・・
## 点の値を変えてみる
- トレースは同じ値で行われる
- はじめっからそうすれば良かった
- でも、これは面倒!
## ライブラリに手を入れる
- RGBを使ってトレースできるようにした!
- 背景色が白でも良くなった!
- でも、もう背景色は黒にしちゃったよ・・・
## トレースする
``` perl
my $figures_ref = Imager::LineTrace::trace( file => $path, ignore => 0 );
```
## PointとLineが検出できた!
```
-------- [0] --------
type :Line
trace_value : 0xFFFFFF
is_closed : 0
( 0, 0)
(63, 0)
-------- [1] --------
type :Point
trace_value : 0x00FF00
is_closed : 0
(56, 1)
-------- [2] --------
type :Line
trace_value : 0xFFFFFF
is_closed : 0
(32, 8)
(39, 8)
-------- [3] --------
type :Line
trace_value : 0xFFFFFF
is_closed : 0
(16,16)
(31,16)
-------- [4] --------
type :Line
trace_value : 0xFFFFFF
is_closed : 0
( 0,24)
(15,24)
-------- [5] --------
type :Line
trace_value : 0xFFFFFF
is_closed : 0
(24,32)
(31,32)
-------- [6] --------
type :Line
trace_value : 0xFFFFFF
is_closed : 0
(32,40)
(39,40)
-------- [7] --------
type :Line
trace_value : 0xFFFFFF
is_closed : 0
(40,48)
(55,48)
-------- [8] --------
type :Point
trace_value : 0xFF0000
is_closed : 0
(48,49)
```
## こんな感じ
``` perl
use v5.14;
use strict;
use warnings;
use lib "../lib";
use Imager::LineTrace;
if ( (not @ARGV) or (not -e $ARGV[0]) ) {
say "Usage:
perl $0 file_path";
exit( 0 );
}
my $figures_ref = Imager::LineTrace::trace( file => $ARGV[0], ignore => 0 );
my @lines = grep {
$_->{type} =~ /Line/
} @{$figures_ref};
{
print "const int n = " . scalar(@lines) . ";\n";
print "const CGFloat xyw[][3] = {\n";
my @buf = ();
for my $line (@lines) {
my $x0 = $line->{points}->[0]->[0]; # pt[0].x
my $y0 = $line->{points}->[0]->[1]; # pt[0].y
my $w = $line->{points}->[1]->[0] - $x0; # pt[1].x - pt[0].x
push @buf, " { " . sprintf("%4.1f, %4.1f, %4.1f", $x0, $y0, $w ) . " }";
}
print join( ",\n", @buf ), "\n";
print "};\n";
}
# ここは使ってない
my @points = grep {
$_->{type} =~ /Point/
} @{$figures_ref};
```
## これをコピペすれば・・・
``` c
const int n = 7;
const CGFloat xyw[][3] = {
{ 0.0, 0.0, 63.0 },
{ 32.0, 8.0, 7.0 },
{ 16.0, 16.0, 15.0 },
{ 0.0, 24.0, 15.0 },
{ 24.0, 32.0, 7.0 },
{ 32.0, 40.0, 7.0 },
{ 40.0, 48.0, 15.0 }
};
```
## まとめ
1. App::pfswatchで画像ファイルを監視
1. 画像ファイルを更新するとソースコードも更新される
1. ビルドしてシミュレーター(or実機)に転送
1. テストプレイ
1. (以下、繰り返し)