前回のZaku認識(1)の続きです。
http://www.moonmile.net/blog/archives/576
物体/動体認識をするときに、白黒を使うことが多いのですが、残念ながら、これでは「シャアザク」と「ザク」の区別がつきません。何故、この2つを区別しなければいけないのか、、、は脇に置いて、区別できる方法で、認識をさせます。
RGB(赤/緑/青)の3値から、白黒画像を作る場合は、YCbCr(YIQ)画像に変換して、Y値だけ残します。
まず、次の画像を見てください。
真ん中にあるガンダムの左上にシャアがいますね。
これをグレー色調にすると、
こんな風に、シャアがザクに隠れてしまいます。
これでは、シャアザクだけを攻撃することはできませんね(笑)。
そんな訳で、YIQからHSV表示に変換して、H値(色相)だけ残します。
サーモグラフィのような画像になりますが、シャアザクの位置が、なんとなくわかります。
同様に次の3つを見比べると、ガンダムの右にシャアがいそうな感じ、ってくぐらいは分かります。
色が単純化されるのは、色相のみ残して、輝度、彩度を一定値にしているからです。
これを使うと、緑の量産ザクと、赤のシャアザクが区別できるんですね。
グレーの場合は、赤緑色盲と一緒で、輝度が同じなので区別がつきません。
RGB/YIQ/HSV表示の相互変換は、こちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 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; } } } |
次回は、背景から動体抽出ですね~。