![書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(6)](https:///re.buildinsider.net/small/bookkinectv2/index/icon.x.png)
書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(6)
平面上のベクトル ― Kinectで学ぶ数学
― Chapter 8 ― 8.1 ―
Kinectではプレイヤーの関節の3次元座標を取得できる。これに関する数学を説明するための基礎として、まずは2次元平面上のベクトルを解説する。
書籍『KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版』から全10本の記事を転載します。前半の第1回~第5回では、UnityやWPFでKinectを活用する方法を解説しました。今回から後半として、「Chapter 8 Kinectで学ぶ数学」を5回にわけて転載します。
書籍転載について
本コーナーは、秀和システム発行の書籍『KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。
『KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版』の詳細や購入は秀和システムのサイトや目次ページをご覧ください。プログラムのダウンロードも、秀和システムのサイトから行えます。
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
■
8.1 平面上のベクトル
8.1.1 2次元ベクトル
すでにご存じの通り、Kinectを用いればプレイヤーの関節の3次元座標を知ることができますが、まずは z 成分を無視して座標平面上にプレイヤーがいると考えてみましょう。
この図の場合、右ひじ A の座標は (a1,a2) 、右手首 B の座標は (b1,b2) です。ここで2次元ベクトルを定義します。
定義1
任意の実数 x1,x2,y1,y2,k に対して、
![(x_1,x_2)+(y_1,y_2)=(x_1+y_1,x_2+y_2)
k(x_1,x_2)=(kx_1,kx_2)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-02.gif)
という足し算と実数倍ができるような実数2つの組 (x1,x2) や (y1,y2) を2次元(数)ベクトルという。ベクトルと特に区別する必要があるとき普通の実数のことをスカラーと呼び、実数倍することをスカラー倍する、などという。
以降ベクトルを表す記号は太字で書きます。ベクトル x,y の和について
![x+y=y+x, k(x+y)=kx+ky](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-03.gif)
が成り立つことに注意してください。また (0,0) を零ベクトルと呼んで 0 と書きます。さらに
![e_1=(1,0), e_2=(0,1)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-04.gif)
とおいて、この e1,e2 のことを基本ベクトルといいます。この基本ベクトル e1,e2 を使えば、任意の2次元ベクトル (x,y) は
![(x,y)=xe_1+ye_2](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-05.gif)
とただ一通りに表すことができます。
定義2
ある与えられた2次元ベクトル u,v と未知のスカラー s,t について
![su+tv=0](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-06.gif)
が成り立つのが s=t=0 に限るとき、ベクトル u,v は線型(一次)独立であるという。また線型独立ではないことを線型(一次)従属であるという。
基本ベクトル e1,e2 はもちろん線型独立ですが、任意の2次元ベクトルが2つのベクトル u,v で
![su+tv](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-07.gif)
とただ一通りに表されるための必要十分条件がベクトル u,v が線型独立であることです。
定義3
2つのベクトル
![x=(x_1,x_2), y=(y_1,y_2)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-08.gif)
に対して、
![x_1 y_1+x_2 y_2](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-09.gif)
をベクトル x,y の内積といい、
![x∙y](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-10.gif)
と書く。さらに x=(x1,x2) として
![√(x∙x)=√(x_1^2+x_2^2)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-11.gif)
を x の長さまたは大きさといい、 |x| で表す。
内積についてはベクトル x,y,z、スカラー k について
![x∙y=y∙x
(kx)∙y=k(x∙y)
x∙(y+z)=x∙y+x∙z](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-12.gif)
が成り立ちます。内積の計算は重要なので慣れておきましょう。
8.1.2 2次元ベクトルの幾何学的意味
2次元ベクトルは長さと方向を持ちます。
8.1.2 2次元ベクトルの幾何学的意味
2次元ベクトルは長さと方向を持ちます。つまり (x1,x2) のとき
![(x_1,x_2)=√(x_1^2+x_2^2)(x_1/√(x_1^2+x_2^2),x_2/√(x_1^2+x_2^2))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-13.gif)
ですから
![(x_1,x_2)=√(x_1^2+x_2^2)(cosθ,sinθ)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-14.gif)
であるような 0 ≤ θ < 2 がただ一つ存在します。したがってベクトルは下図のように座標平面上の有向線分(矢印付きの線分)で表すことができます。なお、方向を表すという意味で長さ 1 のベクトルを方向ベクトルということがあります。
![方向ベクトル](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-15.gif)
ただし、ベクトルの平面上での表し方は無数にあり、平行移動で完全に重ねることができる有向線分はすべて同じベクトルを表すことになります。
![平行移動で完全に重ねることができる有向線分](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-16.gif)
逆に、座標平面上の有向線分はもちろんすべてベクトルで表すことができます。例えば8.1.1節の図で言えば原点 O から右ひじ A に引いた有向線分はベクトル (a1,a2) 、右手首 B に引いた有向線分はベクトル (b1,b2) で表され、見た目は座標と全く一致します。そこで、原点から各点に有向線分を引いて得られるベクトルをその点の位置を表すという意味で位置ベクトルと呼ぶことにします。また、右ひじ A から右手首 B に引いた有向線分を表すベクトルは、有向線分 AB を始点が原点になるよう平行移動して得られる有向線分の終点の位置ベクトルに等しく、B の位置ベクトルから A の位置ベクトルを引いた (b1,b2)-(a1,a2)=(b1-a1,b2-a2) です。
EXERCISE 1
3.5「体(骨格)の検出を行う」(※転載対象外)などを参考に、右手、左手の xy 座標(2次元位置ベクトル)と右手→左手のベクトルの x,y 成分を表示するKinectアプリケーションを作成してください。表示を確認しながら、右手を座標 (1,0) に、左手を (1,1) に持っていきましょう。そのとき右手→左手ベクトルは (0,1) となっていることを確認してください。その後手をうまく動かして右手→左手ベクトルを (1,0) にしてください。
EXERCISE 2
右ひじ→右手首(2次元)ベクトルと左ひじ→左手首(2次元)ベクトルの成分を表示するKinectアプリケーションを作成してください。そして右ひじ→右手首ベクトルと左ひじ→左手首ベクトルを(ほぼ)一致させてください。どのようなポーズを取ればよいでしょう。
線分 AB 上の任意の点の位置ベクトルはパラメータ 0 ≤ t ≤ 1 を用いて
![t(a_1,a_2)+(1-t)(b_1,b_2)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-17.gif)
と表されます。また、0 ≤ t ≤ 1 という制限を外した
![t(a_1,a_2)+(1-t)(b_1,b_2)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-18.gif)
は直線 AB 上の任意の点を表します。
EXERCISE 3
点 A,B,C の位置ベクトルをそれぞれ (2,0), (0,1), (1,1) としたとき、線分 AB と線分 OC との交点 D の位置ベクトルを求めてください。D の位置ベクトルは
![t(2,0)+(1−t)(0,1)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-19.gif)
かつ
![s(1,1)+(1−s)(0,0)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-20.gif)
ですから
![t(2,0)+(1−t)(0,1)=s(1,1)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-21.gif)
であるような値 0 ≤ t,s ≤ 1 を求めれば D の位置ベクトルがわかります。これを応用して、右前腕と左前腕を交差させたとき、xy 平面内で右ひじ→右手首有向線分と左ひじ→左手首有向線分の交点を表示するKinectアプリケーションを作成してください。
ところで、
![|x−y|^2=(x−y)·(x−y)=|x|^2+|y|^2−2x·y](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-22.gif)
ですから、
![x·y=〖|x|^2+|y|^2-|x-y|^2〗/2](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-23.gif)
なので x·y は x,y,x-y の長さだけで決まります。ここで位置ベクトルがそれぞれ x,y であるような点 X,Y をとり、原点を中心に ∆OXY を回転させることを考えます。
![原点を中心に ∆OXY を回転させる](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-24.gif)
回転させた後の点をそれぞれ X′,Y′ とすると当然 OX=OX′, OY=OY′, XY=X′Y′ なので X′,Y′ の位置ベクトルをそれぞれ x′,y′ とすると
![x^'·y^'=x·y](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-25.gif)
です。したがって、
![x^'=|x|(1,0)
y^'=|y|(cosθ,sinθ)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-26.gif)
となるように x,y を回転させても内積の値は変わらず、
![x·y=x^'·y^'=|x||y|cosθ](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-27.gif)
が成り立ちます。ここで θ は ∠XOY=∠X′OY′ であり、この角度をベクトル OX,OY のなす角といい、ふつう 0 ≤ θ ≤ π にとります。すなわち、2つのベクトルの内積はそのなす角を θ(0 ≤ θ ≤ π )として
![x·y=|x||y|cosθ](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-28.gif)
で求めることができます。したがって、ベクトル x,y の長さがともに 0 でなければ、内積が 0 であることと x,y の直交性は一致します。単純計算でベクトル直交しているか否かが分かるので、直交性が問題になる場合には内積がよく用いられます。
EXERCISE 4
右ひじ→右手首(2次元)ベクトルと右ひじ→右肩(2次元)ベクトルの内積を表示するKinectアプリケーションを作成してください。ひじを曲げ伸ばしすることによってその内積を 0 にしてください。そのときひじがKinectから見て直角になっていることを確認しましょう。
8.1.3 平面上の線型写像
任意の2次元ベクトル u が別の2次元ベクトル v に対応しているとき( u=v でもよい)、その対応 T を2次元ベクトル全体から2次元ベクトル全体への写像といい
![v=T(u)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-29.gif)
と書きます。さらに写像 T が k を実数として
![T(u_1+u_2)=T(u_1)+T(u_2)
T(ku)=kT(u)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-30.gif)
という性質を持つとき T を線型写像または線型変換といいます。仮に
![T(e_1)=T(1,0)=(a,c)
T(e_2)=T(0,1)=(b,d)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-31.gif)
とおくと、任意の2次元数ベクトル (x,y)=xe1+ye2 について
![T(x,y)=xT(e_1)+yT(e_2)=x(a,c)+y(b,d)=(ax+by,cx+dy)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-32.gif)
が成り立ちます。したがって線型写像 T は a,b,c,d という4つの実数で決まります。そこでこの a,b,c,d を
![(■(a&b@c&d))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-33.gif)
と長方形に並べて線型写像 T を表す「行列」と呼ぶことにします。
定義4
![(■(a&b@c&d))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-34.gif)
のように実数を縦に2個、横に2個長方形に並べたものを2×2行列という。2×2行列には次のように足し算と実数倍が定義される。
![(■(a_1&b_1@c_1&d_1))+(■(a_2&b_2@c_2&d_2))=(■(a_1+a_2&b_1+b_2@c_1+c_2&d_1+d_2))
k(■(a&b@c&d))=(■(ka&kb@kc&kd))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-35.gif)
また、2×2行列と2×1行列との間には次のようにかけ算が定義され
![(■(a&b@c&d))(■(x@y))=(■(ax+by@cx+dy))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-36.gif)
2×2行列と2×2行列とのかけ算は
![(■(a&b@c&d))(■(x&y@z&w))=(■(ax+bz&ay+bw@cx+dz&cy+dw))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-37.gif)
で定義される。一般に、
![A=(■(A_11&A_12&···&A_1n@A_21&A_22&···&A_2n@⋮&⋮&⋱&⋮@A_m1&A_m2&···&A_mn))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-38.gif)
のように実数を縦に m 個、横に n 個長方形に並べたものを m×n 行列という。足し算と実数倍も2×2行列と同様に定義される。特に、n×n 行列のことを n 次の正方行列という。また、これらの実数 Aij を行列 A の (i,j) 成分という。l×m 行列と m×n 行列の間にはこの順番で次のようにかけ算が定義でき、積は l×n 行列となる:
![(■(A_11&A_12&···&A_1n@A_21&A_22&···&A_2n@⋮&⋮&⋱&⋮@A_m1&A_m2&···&A_mn))(■(B_11&B_12&···&B_1n@B_21&B_22&···&B_2n@⋮&⋮&⋱&⋮@B_m1&B_m2&···&B_mn))=(■(∑_(i=1)^m▒A_1i B_i1&∑_(i=1)^m▒A_1i B_i2&···&∑_(i=1)^m▒A_1i B_in@∑_(i=1)^m▒A_2i B_i1&∑_(i=1)^m▒A_2i B_i2&···&∑_(i=1)^m▒A_2i B_in@⋮&⋮&⋱&⋮@∑_(i=1)^m▒A_li B_i1&∑_(i=1)^m▒A_li B_i2&···&∑_(i=1)^m▒A_li B_in))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-39.gif)
かけ算の定義で「この順番で」と強調したのは行列 A と行列 B のかけ算をするとき、AB が定義されたからといって BA が定義されるとは限らず、もし AB,BA ともに定義されたとしても AB=BA とは限らないからです。
定義5
n 次の正方行列について、
![(■(1&0&···&0@0&1&···&0@⋮&⋮&⋱&⋮@0&0&···&1))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-40.gif)
という対角成分がすべて 1、すなわち (k,k) 成分がすべて 1 (1 ≤ k ≤ n) で、他の成分は 0 であるような行列を n 次の単位行列という。
n 次単位行列を I とすると、任意の m×n 行列 A について
![AI=A](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-41.gif)
任意の n×m 行列 B について
![IB=B](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-42.gif)
さらに任意のn次正方行列Cについては
![CI=IC=C](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-43.gif)
が成り立ちます。このように、単位行列は実数における“1”とよく似た性質を持っています。
定義6
n 次正方行列 A と単位行列 I について、
![AB=BA=I](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-44.gif)
であるような正方行列 B が存在するとき、この B を A の逆行列といい A-1 と書く。
証明を要することですが、正方行列 A,B について AB=I であれば BA=I は必ず成り立ちます。また逆行列は常に存在するとは限りません。たとえば2次の正方行列
![A=(■(a&b@c&d))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-45.gif)
の逆行列を求めるには
![(■(a&b@c&d))(■(x&y@z&w))=(■(1&0@0&1))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-46.gif)
という x,y,z,w についての方程式を解けばよいわけですが、これは
![(■(ax+bz&ay+bw@cx+dz&cy+dw))=(■(1&0@0&1))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-47.gif)
なので連立方程式
![{█(ax+bz=1@cx+dz=0@ay+bw=0@cy+dw=1)┤](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-48.gif)
を解くことになります。1行目の式の両辺に d をかけ、2行目の式の両辺に b をかけて1行目の式から2行目の式を引くと
![(ad-bc)x=d](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-49.gif)
となりますから、これは ad-bc≠0 であるとき、またそのときに限り解くことができます。他の未知数についても同様に ad-bc≠0 のとき、またそのときに限って解くことができて
![A^(-1)=1/(ad-bc) (■(d&-b@-c&a))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-50.gif)
であると分かります。ここで現れた ad-bc を A の行列式と言い、det A と書きます。次数が上がるほど複雑な式にはなりますが、任意の n 次正方行列 B についても同様の式 det B が存在して、逆行列が存在する条件は det B≠0 と書くことができます。
さて、行列は足し算や実数倍をすることができますから、ベクトルの特別な場合だとみなすことがあります。逆にベクトル (x1,x2) を行列だと思うこともでき、成分を横に並べて
![(■(x_1&x_2))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-51.gif)
横ベクトルと呼んだり、縦に並べて
![(■(x_1@x_2))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-52.gif)
縦ベクトルと呼んだりします。縦ベクトルと横ベクトルとを式として等号で結ぶことはありませんが、同じだったはずのものを都合によって縦ベクトルで表したり横ベクトルで表したりということはあり得ますのである程度柔軟に解釈してください。
線型写像 T が
![T(x,y)=(ax+by,cx+dy)](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-53.gif)
と表されるとき
![(■(a&b@c&d))(■(x@x))=(■(ax+by@cx+dy))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-54.gif)
ですから、ベクトルを行列だと思うと線型写像は行列のかけ算で表すことができます。また、このことから行列
![(■(a&b@c&d))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-55.gif)
を線型写像 T を表す行列といいます。
EXERCISE 5
行列
![(■(3&1@2&4))](https:///re.buildinsider.net/small/bookkinectv2/0801/8-1-56.gif)
を用いて右ひじ→右手首2次元ベクトルを線型変換したベクトルと元の右ひじ→右手首2次元ベクトルを矢印もしくは線分で表示するKinectアプリケーションを作成してください。変換前と変換後の2つのベクトルが同じ向きになる方向が、真逆方向同士は1つと数えて2つありますので探してみてください。それらが線型代数で重要な「固有ベクトル」と呼ばれるものです。
■
次回は、空間内のベクトルについて説明します。
※以下では、本稿の前後を合わせて5回分(第4回~第8回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
![書籍転載:KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版(6)](https:///re.buildinsider.net/small/bookkinectv2/index/icon.s.png)
5. Kinect WPF ControlsでWPFアプリでもジェスチャーを活用しよう
WPFアプリにKinectを操作するための機能を実装する場合にはKinect WPF Controlsが便利だ。その機能概要を紹介する。