前回の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;
}
}
}
次回は、背景から動体抽出ですね~。






