前回のZaku認識(1)の続きです。
http://www.moonmile.net/blog/archives/576
物体/動体認識をするときに、白黒を使うことが多いのですが、残念ながら、これでは「シャアザク」と「ザク」の区別がつきません。何故、この2つを区別しなければいけないのか、、、は脇に置いて、区別できる方法で、認識をさせます。
RGB(赤/緑/青)の3値から、白黒画像を作る場合は、YCbCr(YIQ)画像に変換して、Y値だけ残します。
まず、次の画像を見てください。
真ん中にあるガンダムの左上にシャアがいますね。
これをグレー色調にすると、
こんな風に、シャアがザクに隠れてしまいます。
これでは、シャアザクだけを攻撃することはできませんね(笑)。
そんな訳で、YIQからHSV表示に変換して、H値(色相)だけ残します。
サーモグラフィのような画像になりますが、シャアザクの位置が、なんとなくわかります。
同様に次の3つを見比べると、ガンダムの右にシャアがいそうな感じ、ってくぐらいは分かります。
色が単純化されるのは、色相のみ残して、輝度、彩度を一定値にしているからです。
これを使うと、緑の量産ザクと、赤のシャアザクが区別できるんですね。
グレーの場合は、赤緑色盲と一緒で、輝度が同じなので区別がつきません。
RGB/YIQ/HSV表示の相互変換は、こちら
namespace zaku.monoeye { // RGB表示系クラス // r: 赤 // g: 緑 // b: 青 public class RGB { public double r; public double g; public double b; public RGB() { r = g = b = 0; } // 正規化されたRGB値(0.0-1.0) public RGB( double r, double g, double b ) { this.r = r; this.g = g; this.b = b; } // ディスプレイのRGB値(0-255) public RGB(Color col) { this.r = ((double)col.R) / 255.0; this.g = ((double)col.G) / 255.0; this.b = ((double)col.B) / 255.0; } public Color ToColor() { int r, g, b; r = (int)(this.r * 255); g = (int)(this.g * 255); b = (int)(this.b * 255); if ( r < 0 ) r = 0; if ( g < 0 ) g = 0; if ( b < 0 ) b = 0; if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; Color col = Color.FromArgb(255, r, g, b ); return col; } public YIQ ToYIQ() { YIQ yiq = new YIQ( 0.2990 * r + 0.5870 * g + 0.1140 * b, 0.5959 * r - 0.2750 * g - 0.3210 * b, 0.2065 * r - 0.4969 * g + 0.2904 * b ); return yiq; } } // YIQ表示系クラス // y: 輝度 // i: 青み成分 // q: 赤み成分 public class YIQ { public double y; public double i; public double q; public YIQ() { y = i = q = 0.0; } public YIQ( double y, double i, double q ) { this.y = y; this.i = i; this.q = q; } public RGB ToRGB() { RGB rgb = new RGB( 1.001 * y + 0.955 * i + 0.622 * q, 0.999 * y - 0.272 * i - 0.648 * q, 1.004 * y - 1.106 * i + 1.704 * q ); return rgb; } public HSV ToHSV() { HSV hsv = new HSV(); hsv.h = Math.Atan2(i, q); hsv.s = Math.Sqrt(i * i + q * q); hsv.v = y; return hsv; } } // HSV表示系クラス // h: 色相 // s: 彩度 // v: 輝度 public class HSV { public double h; public double s; public double v; public HSV() { h = s = v = 0.0; } public HSV( double h, double s, double v ) { this.h = h; this.s = s; this.v = v; } public YIQ ToYIQ() { YIQ yiq = new YIQ(); yiq.y = v; yiq.i = s * Math.Sin( h ); yiq.q = s * Math.Cos(h); return yiq; } } }
次回は、背景から動体抽出ですね~。