2006-11-18
■[画像処理] AS3で「ナンシー小関風パッチもん版画」作成ソフトを作る

今年の夏ごろ話題になったあのソフトをAS3に移植するというちょっと無謀な企画だ。
そこから辿ってソースファイルnancyKOseki20060719.cppを得ることができる。意外と短いので驚いた。画像処理はOpenCVを使っているので、OpenCVの仕様さえ分かれば、なんとか似たことはAS3でも可能だ。
さてC++を読むのは結構つらかったのだけど何とか読みきった。ナンシー小関風画像処理の概略はこうだ。たぶん。
- b0 ← Glayscale(ソースビットマップ)
- b1 ← GaussianBlur(b0, 細かさ)
- b2 ← GaussianBlur(b0, 細かさ+線の太さ)
- b3 ← Sub(b1, b2)
- b4 ← Threshhold(b3, 線際)
- b5 ← Nancy(b4, b1, b2)
- b6 ← Open(b5, 単純さ)
- b7 ← Close(b6, 単純さ)
このなかで、Sub()とNancy()以外は今までの画像処理入門で作ってきたのを使いまわせる。
GaussianBlur()はちょっと違うかもしれないけど、AS3リファレンスによるとflash.filters.BlurFilterをBitmapFilterQuality.HIGHで使うと「ガウスぼかしに近似したものになります」と書いてあるのでこれをありがたく使わせてもらう。
Sub (差)
ここではSubは部分の意味じゃなくて単純に引き算なのだ。二つの画像から、画素の明るさを単純に引き算した画像を作る。OpenCVのcvSubについて色々調べてたら、引いた結果値がマイナスになることは無く、0で自動的にクリッピングされるとのことらしい。
/** 引き算
* @param dst デスティネーション
* @param src1 引かれる側
* @param src2 引く側
*/
public function Sub(dst:BitmapData, src1:BitmapData, src2:BitmapData):void {
for (var x:int = 0; x < src1.width; x++) {
for (var y:int = 0; y < src1.height; y++) {
var c1:int = src1.getPixel(x, y) & 255;
var c2:int = src2.getPixel(x, y) & 255;
var c:int = c1 - c2;
c = c < 0 ? 0 : c;
dst.setPixel(x, y, (c << 16) | (c << 8) | c);
}
}
}
入出力画像は同じ幅と高さであることを前提にしている。
また入力画像はグレースケールであることを前提にしているので青成分しか見てない。
Nancy
さて肝の Nancy() なのだが、これはcppのソースをじっくり見て、たぶんこんなので同じ処理になっていると思う。
/** エッジ部分とベタ部分の合成をする
* @param dst デスティネーション
* @param src0 線際閾値処理の結果
* @param src1 細かさ平滑化の結果
* @param src2 細かさ+太さ平滑化の結果
* @param fill ベタ
*/
public function Koseki(dst:BitmapData, src0:BitmapData, src1:BitmapData, src2:BitmapData, fill:int):void {
for (var x:int = 0; x < src0.width; x++) {
for (var y:int = 0; y < src0.height; y++) {
var s0:int = src0.getPixel(x, y) & 255;
var s1:int = src1.getPixel(x, y) & 255;
var s2:int = src2.getPixel(x, y) & 255;
var d:int;
if (s2 > s1 || s2 < fill)
if (s2 < fill)
if (s0 == 255)
d = 255;
else
d = 0;
else
if (s0 == 0)
d = 0;
else
d = 255;
else
if (s2 > 255 - fill)
if (s0 == 0)
d = 255;
else
d = 0;
else
if (s0 == 0)
d = 255;
else
d = 0;
dst.setPixel(x, y, (d << 16) | (d << 8) | d);
}
}
}
例によって入出力画像は全部同じ幅と高さ、グレースケールであることを前提にしている。
デモ
さて本家は画像ファイルをDnDすればいいようになってたけど、Flashでは無理なので、カメラ画像を取り込むようにした。
http://space.geocities.jp/flashr0d/nancy.html
スライダを動かすと微調整できる。
なんだか本家ほど精度が良くない気がするんだけど、これは主に画像処理に関するオイラの技能不足ということで、ひとつよしなに。





