透過画像を復元したいときの話
状況
まず、何らかの透過画像が存在するとします。
元画像の例
実際にはこの画像は持っていないとします。ただし、これを白背景に貼りつけた画像と、黒背景に貼りつけた画像は得られたとします。
白背景の例 黒背景の例
これらから、元画像を(ある程度の精度で)復元することを考えます。
前提知識
透過画像の合成の計算方法について触れます。Alpha compositing (Wikipedia) にある A over B の合成方法を用います。たぶんメジャーなので。
各画素・RGB の各値に対して、それぞれ独立に行います。
画素
このとき、
考察
白背景と黒背景の画像に関して、それぞれ
白背景の画素
よって、以下が得られます。
よって、
ここで、
これに基づいて復元が可能です。
復元画像の例
合成の際に(整数に丸めるため)誤差が生じますが、人間[1]の目にわかる程度の差はなさげです。背景は実際には白と黒ではなくても可能そうです(が、誤差が大きくなりそうな気がします)。
ビット数が 8 程度なら、全通り作っておいて表引きしてもよさそうな気もします。16 ビットある場合は表引きでは大変そうです。
Rust で書くとこんな感じ。
fn transparent(white: [u8; 4], black: [u8; 4]) -> [u8; 4] {
let alpha = (0..3).map(|i| 255 - (white[i] - black[i])).max().unwrap();
if alpha == 0 {
return [0; 4];
}
let mut res = [0, 0, 0, alpha];
for i in 0..3 {
res[i] = ((255 * black[i] as u16) / alpha as u16) as u8;
}
res
}
おわり
あまり役に立つ機会はなさそう。
ポエム
実は、プログラミング始めたての頃(たぶん 7–8 年くらい前)に書いたものがこれでした[2]。久々に思い出したのでまとめました。あなたは始めたての頃に書いたものを覚えていますか?
最近は(実務を除いては)競プロくらいしかしていなくて、当時の方がいろいろやっていたのではないかという気もしています。
Discussion