2014 tco marathon round 3 (yowa)
TRANSCRIPT
2014 TCO Marathon Round 32014 TCO Marathon Round 3
CollageMakerCollageMaker- - 画像を敷き詰めて画像を作る 画像を敷き詰めて画像を作る --
参加メモ参加メモ
@yowa
どんな問題?
● 一つの大きな画像(原画像: 長辺 300px)と、
どんな問題?
● 一つの大きな画像(原画像: 長辺 300px)と、● 200個の小さな画像(長辺 100px)が与えられる
どんな問題?
● 小さい画像群から– 使うやつを選んで– 縮小させて(縦横スケールは任意。拡大・回転はダメ)
– 敷き詰めることで、
どんな問題?
● 原画像を再現したい!– スコアは sqrt((pixel ごとの輝度差)^2 の平均)
● ようするに、輝度誤差の標準偏差
出力例
● 目を細めれば、なんとなくわかる
出力例
● 目を細めれば、なんとなくわかる
出力例
● 目を細めれば、なんとなくわかる…??
出力例
● 目を細めれば、なんとなくわかるわ
画像のパターンマッチ
● 小画像をいろんなサイズに縮小して、● 原画像のいろんな場所にマッチさせてみて、● 誤差が少なかったとこを採用して、● 原画像全体を、重なりや余りナシで覆い尽くす
画像のパターンマッチ
● 小画像をいろんなサイズに縮小して、● 原画像のいろんな場所にマッチさせてみて、● 誤差が少なかったとこを採用して、● 原画像全体を、重なりや余りナシで覆い尽くす
いかにも重くてめんどそう!
やったこと(概要)
● 原画像を覆う長方形領域1つからスタート● 領域が200個になるまで…
– 領域を1つ選んで、分散が小さくなるように2分割
– いちばん分散が小さくなった分割を採用● 領域が1個ふえる
– 各領域に画像を割り当てる– スコアがよくなってたら採用、ループ継続
● スコア悪化なら、領域選択からやりなおし
やったこと(概要)
● 原画像を覆う長方形領域1つからスタート● 領域が200個になるまで…
– 領域を1つ選んで、分散が小さくなるように2分割
– いちばん分散が小さくなった分割を採用● 領域が1個ふえる
– 各領域に画像を割り当てる– スコアがよくなってたら採用、ループ継続
● スコア悪化なら、領域選択からやりなおし
分散が小さくなる分割?
● 分散 = 平均値との2乗誤差の総和の平均● スコア^2 = 作成画像との2乗誤差の総和の平均
分散 =
領域内を平均値で塗りつぶした時のスコア^2
分散が小さくなる分割?
● 分散が小さくなるように分割してゆく
Score: 59.45 Score: 47.58 Score: 44.08 Score: 41.49
分割
領域を平均色で塗りつぶし
何がうれしいの?
● 小画像は200個もあるし、● 小画像は縮小して貼るから
細かいデティールは消えるし、● 各領域の「平均色塗りつぶし」に
近い画像が1個くらい
みつかるんじゃね?
何がうれしいの?
● 小画像は200個もあるし、● 小画像は縮小して貼るから
細かいデティールは消えるし、● 各領域の「平均色塗りつぶし」に
近い画像が1個くらい
みつかるんじゃね?
\ て き と う /
やったこと(概要)
● 原画像を覆う長方形領域1つからスタート● 領域が200個になるまで…
– 領域を1つ選んで、分散が小さくなるように2分割
– いちばん分散が小さくなった分割を採用● 領域が1個ふえる
– 各領域に画像を割り当てる– スコアがよくなってたら採用、ループ継続
● スコア悪化なら、領域選択からやりなおし
各領域に小画像を割り当てる
● 領域(M個)と小画像(N個)について、– 領域のサイズに合わせて小画像を縮小し– 領域内での2乗誤差を計算
● 領域と小画像の最適な組み合わせを求める– 上で求めた2乗誤差の和が最小になる組み合わせ
画像の縮小
● 小画像(W, H)を領域(w, h)に縮小 (W w, H h)≧ ≧● 縮小は面積平均法で行う(問題仕様で定義)
● 定義通りだと whWH 回の演算● とりあえず WH になる● それでも重い● wh くらいにできない?
4x4 → 3x3
3倍して、各区画を平均
(多くの場合で WH と wh は 10倍以上違う)
画像の(不正確な)縮小
● 整数pixelで小画像を(w,h)に分割● 各分割領域の平均は、累積和を使って O(1)
● よって O(wh) で求まる● 本来の縮小方法じゃないから
もちろん誤差がある(気にしない)
● 端の処理をちゃんとやれば
正確な値も O(wh) でいける気がする(めんどい)
4x4 → 3x3
(累積和)
● 左上からの総和をあらかじめ求めておく O(WH)
● 任意の領域の総和が O(1) で計算できる
● 二乗の総和も同じように求めておくと
任意の領域の分散も O(1) でいける
赤い領域の総和を求める
各領域に小画像を割り当てる
● 領域(M個)と小画像(N個)について、– 領域のサイズに合わせて小画像を縮小し– 領域内での2乗誤差を計算
● 領域と小画像の最適な組み合わせを求める– 上で求めた2乗誤差の和が最小になる組み合わせ
割当て問題 (assignment problem)
● 完全2部グラフ(V,W)と、コスト関数 c: V×W→R
● コスト総和が最小になる最大マッチングを求める
● 最大流の応用で O(|V|^2|W|)で求まる
(ハンガリアン法)
割当て問題 (assignment problem)
● 完全2部グラフ(V,W)と、コスト関数 c: V×W→R
● コスト総和が最小になる最大マッチングを求める
● 最大流の応用で O(|V|^2|W|)で求まる
(ハンガリアン法)
● オレには実装できなかったよ…● 2-opt (2箇所の画像を入替え改善するなら採用)
でごまかした(= 最適解ではない)
やったことまとめ
● 分割して割当て● スコアは良くなった?
– YES: さらに分割しよう
– NO: いまの分割は undo してやりなおし
やった細かいこと
● もとまった best 解の分割位置を調整– 各領域に対する画像の割当ては固定して、
分割線を動かして改善しないか見てみる
(全体で2%くらいスコア改善した)
やった細かいこと
● 領域分割の undo があったら、
「さっき縦分割だったからこんどは横分割な」
みたいに方向を変えてる● 同じ領域で何回も undo 発生したら、
「もうこの領域は分割しません!」宣言しとく● その領域に割当てられる画像が変わったら
宣言撤回する
やらなかった(やれなかった)こと
● 画像の特徴をつかって先に割当て位置を決める● 目標画像を縮小しといて概算を高速にする● 分割に分散以外の評価値を入れる
上半分と下半分の平均が同じ
→ 分割しても分散へらない
→ 今回のやり方だと分割できない
やれなかったこと
● 領域を一度に3分割(以上)する
or スコアの落ちる分割を(特定の条件で)許す
現状の問題点
雑感
● 割り算は重い
– 画像縮小時、こんなコードで WH 回割り算してた
– ループ外で事前計算にした (割り算: W+H 回)
– 全体の実行時間が半分くらいになった(脱力)
(ブレゼンハムっぽくやれば割り算いらないんじゃね?)
雑感
● 実行時間、不安定じゃね?– 昔のマラソンマッチは、example に同じコード投げたら
10ms くらいの誤差しかなかった気がする
– でも今回は(最近は?) 簡単に100ms くらいブレる
– 時間調整むずいよなー
どうでもいい個人情報
● example submit は full submit の直前しかやらない● なので基本的に両者の数は等しくなる● standing を見て両者の数がズレてたら、
– submit するソース間違えてるよwww
– 想定外のエラーやTLEで戸惑ってるよwww
みたいな想像をしましょう
おしまい ―――――――――― 製作・著作 @yowa