Zaku認識(2)

前回のZaku認識(1)の続きです。
http://www.moonmile.net/blog/archives/576

物体/動体認識をするときに、白黒を使うことが多いのですが、残念ながら、これでは「シャアザク」と「ザク」の区別がつきません。何故、この2つを区別しなければいけないのか、、、は脇に置いて、区別できる方法で、認識をさせます。

RGB(赤/緑/青)の3値から、白黒画像を作る場合は、YCbCr(YIQ)画像に変換して、Y値だけ残します。

まず、次の画像を見てください。

<001>
20100208_001

真ん中にあるガンダムの左上にシャアがいますね。
これをグレー色調にすると、

<002>
20100208_002

こんな風に、シャアがザクに隠れてしまいます。
これでは、シャアザクだけを攻撃することはできませんね(笑)。

そんな訳で、YIQからHSV表示に変換して、H値(色相)だけ残します。

<003>
20100208_003

サーモグラフィのような画像になりますが、シャアザクの位置が、なんとなくわかります。

同様に次の3つを見比べると、ガンダムの右にシャアがいそうな感じ、ってくぐらいは分かります。

<004>
20100208_004

<005>
20100208_005

<006>
20100208_006

色が単純化されるのは、色相のみ残して、輝度、彩度を一定値にしているからです。
これを使うと、緑の量産ザクと、赤のシャアザクが区別できるんですね。
グレーの場合は、赤緑色盲と一緒で、輝度が同じなので区別がつきません。

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;
  }
 }
}

次回は、背景から動体抽出ですね~。

カテゴリー: 雑談 パーマリンク