【OpenCV+matplotlib】ベクトル場をカラーマップで良い感じに表示する方法

# 概要
ベクトル場の角度と大きさをカラーマップで表示したい場合がある。そんなときに便利なのがmatplotlibの[quiver](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.quiver.html)であるが、実はOpenCVのHSV空間を組み合わせるとベクトル場の角度と大きさを一目で見やすく表示できる。
本記事は筆者が個人的に見やすいと思うベクトル場の表示方法について紹介する。

# 実装
Google Colabで作成した本記事のコードは、[こちら](https://colab.research.google.com/drive/1RoMFoqyV_GgBScw-R-VgSzVjFUTlUj8o?usp=sharing)にあります。
## 各種インポート
```Python:各種インポート
import cv2
import matplotlib.pyplot as plt
import numpy as np
```
実行時の各種バージョン

| Name | Version |
|:-:|:-:|
| opencv-python | 4.6.0.66 |
| matplotlib | 3.2.2 |
| numpy | 1.21.6 |

## 準備
### hsv, jetのカラーマップを見やすくするために背景を黒塗りにする
```Python:
plt.style.use('dark_background')
```
### 座標変換用の関数
matplotlibの[Secondary Axis](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/secondary_axis.html)を使って、ピクセル座標とベクトル場の座標の軸のスケールを調整する関数である。例えば、[ベクトル場の角度を背景にカラーマップ表示](#ベクトル場の角度を背景にカラーマップ表示)のように背景にベクトル場の角度情報を``ax.imshow()``で追加する場合、通常軸はピクセル座標で表示されてしまうが、この関数を適用すると軸のスケールを元のベクトル場のスケールに変換して表示できる。ただし、以降の``ax.set_aspect('equal')``は、**ピクセル座標でのアスペクト比が統一される**ので、厳密にベクトル場でのアスペクト比が統一されない場合があるので注意してください。この関数を適用する上でアスペクト比が調節されないケースは、**ベクトルの取得座標間隔が``X``と``Y``で異なるとき**である。
```Python:ピクセル座標とベクトル場の座標変換用の関数
def px2coord_axis(ax, X, Y):
    """
    input
    ax: matplotlib axis object
    X: 1D or 2D equally spaced vector field x array
    Y: array of vector fields y of the same dimension as `X`
    output
    ax: matplotlib ax object
    secax_x: vector field x coord object
    secax_y: vector field y coord object
    description
    Function to convert axis labels from pixel coordinates to vector field coordinates.
    """
    if X.ndim == 2:
        X_start = X[0, 0]
        X_step = X[0, 1] - X[0, 0]
        Y_start = Y[0, 0]
        Y_step = Y[1, 0] - Y[0, 0]
    else:
        X_start = X[0]
        X_step = X[1] - X[0]
        Y_start = Y[0]
        Y_step = Y[1] - Y[0]
    ax.tick_params(labelbottom=False, labelleft=False)
    secax_x = ax.secondary_xaxis('bottom',
                                functions=(lambda x: x*X_step + X_start, lambda x: (x - X_start) / X_step))
    secax_y = ax.secondary_yaxis('left',
                                functions=(lambda x: x*Y_step + Y_start, lambda x: (x - Y_start) / Y_step))
    return ax, secax_x, secax_y
```
### サンプルのベクトル場の準備
注意点として、[``cv2.cartToPolar``](https://docs.opencv.org/3.4/d2/de8/group__core__array.html#gac5f92f48ec32cacf5275969c33ee837d)の入力の``U``, ``V``は、float型の同じ型である必要がある。``cv2.cartToPolar(U, V, angleInDegrees=True)``は、``mag``と``ang``にそれぞれ各座標に対応したベクトルの大きさと角度が入った配列が入る。``angleInDegrees=True``とするとこで、``ang``には反時計回りを正にした0°~360°の度数法に基づく角度が入る。サンプルでは、放射状のベクトルを用意した。
```Python:サンプルのベクトル場
X = np.arange(-10, 11, 1, dtype=np.float64)
Y = np.arange(-10, 11, 1, dtype=np.float64)
U, V = np.meshgrid(X, Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
X_shape, Y_shape = X.shape[0], Y.shape[0]  # X, Yが1次元配列の場合
# X_shape, Y_shape = X.shape[1], Y.shape[0]  # X, Yが2次元配列の場合
```
サンプルのベクトル場を表示して確認する。
```Python:ベクトル場を表示
fig, ax = plt.subplots(figsize=(10, 8))
ax.quiver(X, Y, U, V, color='w')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/ff3008dc-87e7-8f59-9f0b-4e4238e63c38.png)

## 方法
### ベクトル場の角度をカラーマップ表示
```Python:ベクトル場の角度をカラーマップ表示
fig, ax = plt.subplots(figsize=(10, 8))
Q = ax.quiver(X, Y, U, V, ang, cmap='hsv')
ax.set_xlabel('X')
ax.set_ylabel('Y')
fig.colorbar(Q, label='vector angle (degree)')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/d7d0cf65-ae4a-fbbd-c0cf-f3d6339b6a36.png)

### ベクトル場の大きさをカラーマップ表示
```Python:ベクトル場の大きさをカラーマップ表示
fig, ax = plt.subplots(figsize=(10, 8))
Q = ax.quiver(X, Y, U, V, mag, cmap='jet')
ax.set_xlabel('X')
ax.set_ylabel('Y')
fig.colorbar(Q, label='vectorrr size')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/5beca70e-677f-684a-f08a-8aa0af50fce1.png)

### ベクトル場の角度を背景にカラーマップ表示
```Python:ベクトル場の角度を背景にカラーマップ表示
fig, ax = plt.subplots(figsize=(10, 8))
cmap = plt.imshow(ang, cmap='hsv', origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
fig.colorbar(cmap, label='vector angle (degree)')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/d068061b-caff-b58e-fadf-904c23ff9af3.png)

### ベクトル場の大きさを背景にカラーマップ表示
```Python:ベクトル場の大きさを背景にカラーマップ表示
fig, ax = plt.subplots(figsize=(10, 8))
cmap = plt.imshow(mag, cmap='jet', origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
fig.colorbar(cmap, label='vector size')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/78ff60b8-c7ea-26e2-bda9-b4fef721f004.png)

### HSV色空間にベクトル場の角度に色相を、大きさに角度を対応させて表示
``hsv``はHSV色空間の配列であり、``hsv``の配列の定義は以下の通りである。
* ``hsv[..., 0]``は色相を表し、0~180で定義される。
* ``hsv[..., 1]``は彩度を表し、0~255で定義される。ベクトル場を扱うときは、基本的に255で問題ないと思われる。
* ``hsv[..., 2]``は明度を表し、0~255で定義される。

``cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)``でRGB画像に変換している。

```Python:HSV色空間にベクトル場の角度に色相を、大きさに角度を対応させて表示
hsv = np.zeros((Y_shape, X_shape, 3), dtype='uint8')
hsv[..., 0] = ang / 2
hsv[..., 1] = 255
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
flow_rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)

fig, ax = plt.subplots(figsize=(8, 8))
ax.imshow(flow_rgb, origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/8ee51b62-4ffb-c45f-c904-c80b5d0dffb9.png)

### HSV色空間にベクトル場の大きさに色相と明度を対応させて表示
```Python:HSV色空間にベクトル場の大きさに色相と明度を対応させて表示
hsv = np.zeros((Y_shape, X_shape, 3), dtype='uint8')
hsv[..., 0] = cv2.normalize(mag, None, 0, 180, cv2.NORM_MINMAX)
hsv[..., 1] = 255
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
flow_rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)

fig, ax = plt.subplots(figsize=(8, 8))
ax.imshow(flow_rgb, origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/37ee9dc7-6a97-1299-5c4d-3ed9195760d3.png)

# 少し構造のあるベクトル場での例
```Python:少し構造のあるベクトル場
X, Y = np.meshgrid(np.arange(0, 3 * np.pi, .2), np.arange(0, 2 * np.pi, .2))
U = np.cos(X)
V = np.sin(Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
X_shape, Y_shape = X.shape[1], Y.shape[0]  # 2次元配列の場合
```

ベクトル場を表示([ベクトル場を表示](``figsize=(15, 8)``としてベクトル場を表示)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/3d664ae8-55c2-57c4-8d7a-3f624ce344e5.png)

ベクトル場の角度をカラーマップ表示([ベクトル場の角度をカラーマップ表示](#ベクトル場の角度をカラーマップ表示)の``figsize=(15, 8)``としたコード)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/7038ec33-9879-ed62-5d17-ebb5178859a7.png)

ベクトル場の大きさをカラーマップ表示([ベクトル場の大きさをカラーマップ表示](#ベクトル場の大きさをカラーマップ表示)の``figsize=(15, 8)``としたコード)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/41e88f31-f9c2-da75-b07d-97d905b63efd.png)

ベクトル場の角度を背景にカラーマップ表示([ベクトル場の角度を背景にカラーマップ表示](#ベクトル場の角度を背景にカラーマップ表示)の``figsize=(15, 8)``としたコード)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/64dd26ed-dba7-6fc8-87c8-5322dc653504.png)

ベクトル場の大きさを背景にカラーマップ表示([ベクトル場の大きさを背景にカラーマップ表示](#ベクトル場の大きさを背景にカラーマップ表示)の``figsize=(15, 8)``としたコード)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/f4230833-0c87-382e-b459-c95dad3dcd8b.png)


HSV色空間にベクトル場の角度に色相を、大きさに角度を対応させて表示([HSV色空間にベクトル場の角度に色相を、大きさに角度を対応させて表示](#hsv色空間にベクトル場の角度に色相を大きさに角度を対応させて表示)の``figsize=(15, 8)``としたコード)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/e718ef4b-149d-b4dc-2505-e5daa83373c2.png)

HSV色空間にベクトル場の大きさに色相と明度を対応させて表示([HSV色空間にベクトル場の大きさに色相と明度を対応させて表示](#hsv色空間にベクトル場の大きさに色相と明度を対応させて表示)の``figsize=(15, 8)``としたコード)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/3a4fc761-d009-f965-57aa-66c9a7805a12.png)

# 補足(カラーマップを任意の範囲で設定)
matplotlibのquiverは、カラーマップの色の表示範囲(matplotlibに良くあるvmin, vmax等)の引数は2022/08/29時点ではなく、また角度の表示範囲は360°を超えると不連続なので、少し複雑で以下のコードを参考にしていただきたい。

<details><summary>カラーマップ任意の範囲で表示するためのコード</summary>

## 関数の準備
```Python:任意の範囲のカラーマップ用の関数
def any_angle_only(mag, ang, ang_min, ang_max):
    """
    input
    mag: `cv2.cartToPolar` method `mag` reuslts
    ang: `cv2.cartToPolar` method `ang` reuslts
    ang_min: start angle of degree
    ang_max: end angle of degree
    output
    any_mag: array of replace any out of range `ang` with nan
    any_ang: array of replace any out of range `mag` with nan
    description
    Replace any out of range `mag` and `ang` with nan.
    """
    any_mag = np.copy(mag)
    any_ang = np.copy(ang)
    ang_min %= 360
    ang_max %= 360
    if ang_min < ang_max:
        any_mag[(ang < ang_min) | (ang_max < ang)] = np.nan
        any_ang[(ang < ang_min) | (ang_max < ang)] = np.nan
    else:
        any_mag[(ang_max < ang) & (ang < ang_min)] = np.nan
        any_ang[(ang_max < ang) & (ang < ang_min)] = np.nan
        any_ang[ang <= ang_max] += 360
    return any_mag, any_ang

def any_size_only(mag, ang, mag_min, mag_max):
    """
    input
    mag: `cv2.cartToPolar` method `mag` reuslts
    ang: `cv2.cartToPolar` method `ang` reuslts
    mag_min: range min mag
    mag_max: range max mag
    output
    any_mag: array of replace any out of range `ang` with nan
    any_ang: array of replace any out of range `mag` with nan
    description
    Replace any out of range `mag` and `ang` with nan.
    """
    any_mag = np.copy(mag)
    any_ang = np.copy(ang)
    any_mag[(mag < mag_min) | (mag_max < mag)] = np.nan
    any_ang[(mag < mag_min) | (mag_max < mag)] = np.nan
    return any_mag, any_ang
```
## ベクトル場を任意の範囲の角度のみでカラーマップ
ベクトル場を任意の範囲の角度のみでカラーマップで表すことで、ベクトル場の角度に対する色の感度を上げて詳細に見ることができる。ただ、360°を超える範囲を指定すると不連続なので少し複雑で、自作の``any_angle_only``関数で、角度を反時計回りに指定する。``ang_min``は反時計回りの角度の始まり、``ang_max``反時計回りの角度の終わりを度数法で指定する。例の``any_angle_only(mag, ang, 270, 60)``は、``any_angle_only(mag, ang, 270, 420)``としても同様に機能する。

```Python:ベクトル場を任意の範囲の角度のみでカラーマップ
"""サンプルのベクトル場"""
X = np.arange(-10, 11, 1, dtype=np.float64)
Y = np.arange(-10, 11, 1, dtype=np.float64)
U, V = np.meshgrid(X, Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
any_mag, any_ang = any_angle_only(mag, ang, 270, 60)  # 270°から60°のみでカラーマップ表示
# any_mag, any_ang = any_angle_only(mag, ang, 270, 420)  # こちらでも可能
X_shape, Y_shape = X.shape[0], Y.shape[0]  # 1次元配列の場合

"""ベクトル場の角度をカラーマップ表示"""
fig, ax = plt.subplots(figsize=(10, 8))
ax.quiver(X, Y, U, V, color='w')
Q = ax.quiver(X, Y, U, V, any_ang, cmap='hsv')
fig.colorbar(Q, label='vector angle (degree)')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/31a47ee3-3b83-f7b9-cc94-c9bbe864c486.png)

## ベクトル場を任意の範囲の大きさのみでカラーマップ
```Python:ベクトル場を任意の範囲の大きさのみでカラーマップ
"""サンプルのベクトル場"""
X = np.arange(-10, 11, 1, dtype=np.float64)
Y = np.arange(-10, 11, 1, dtype=np.float64)
U, V = np.meshgrid(X, Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
any_mag, any_ang = any_size_only(mag, ang, 5, 10)
X_shape, Y_shape = X.shape[0], Y.shape[0]  # 1次元配列の場合

"""ベクトル場の大きさをカラーマップ表示"""
fig, ax = plt.subplots(figsize=(10, 8))
ax.quiver(X, Y, U, V, color='w')
Q = ax.quiver(X, Y, U, V, any_mag, cmap='jet')
fig.colorbar(Q, label='vectorrr size')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/760fa0cc-2587-ad1e-a61a-f540c4098b3b.png)

## ベクトル場を任意の範囲の角度のみで背景にカラーマップ
```Python:ベクトル場を任意の範囲の角度のみで背景にカラーマップ
"""サンプルのベクトル場"""
X = np.arange(-10, 11, 1, dtype=np.float64)
Y = np.arange(-10, 11, 1, dtype=np.float64)
U, V = np.meshgrid(X, Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
any_mag, any_ang = any_angle_only(mag, ang, 270, 60)  # 270°から60°のみでカラーマップ表示
# any_mag, any_ang = any_angle_only(mag, ang, 270, 420)  # こちらでも可能
X_shape, Y_shape = X.shape[0], Y.shape[0]  # 1次元配列の場合

"""ベクトル場の角度を背景にカラーマップ表示"""
fig, ax = plt.subplots(figsize=(10, 8))
cmap = plt.imshow(any_ang, cmap='hsv', origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
fig.colorbar(cmap, label='vector angle (degree)')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/df11496c-f844-6dc2-0bb6-1bc0bdf404e0.png)

## ベクトル場を任意の範囲の大きさのみで背景にカラーマップ
```Python:ベクトル場を任意の範囲の大きさのみで背景にカラーマップ
"""サンプルのベクトル場"""
X = np.arange(-10, 11, 1, dtype=np.float64)
Y = np.arange(-10, 11, 1, dtype=np.float64)
U, V = np.meshgrid(X, Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
any_mag, any_ang = any_size_only(mag, ang, 5, 10)
X_shape, Y_shape = X.shape[0], Y.shape[0]  # 1次元配列の場合

"""ベクトル場の大きさを背景にカラーマップ表示"""
fig, ax = plt.subplots(figsize=(10, 8))
cmap = plt.imshow(any_mag, cmap='jet', origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
fig.colorbar(cmap, label='vector size')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/7ace419e-71e6-534f-460e-34e1d7fb3987.png)

## HSV空間にベクトル場を任意の範囲の角度に色相を、大きさに明度を対応させて表示
``cv2.normalize(any_ang, None, 0, 180, cv2.NORM_MINMAX)``とすることで、0~180に正規化するのがポイントである。
```Python:HSV空間にベクトル場を任意の範囲の角度に色相を、大きさに明度を対応させて表示
"""サンプルのベクトル場"""
X = np.arange(-10, 11, 1, dtype=np.float64)
Y = np.arange(-10, 11, 1, dtype=np.float64)
U, V = np.meshgrid(X, Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
any_mag, any_ang = any_angle_only(mag, ang, 270, 60)  # 270°から60°のみでカラーマップ表示
# any_mag, any_ang = any_angle_only(mag, ang, 270, 420)  # こちらでも可能
X_shape, Y_shape = X.shape[0], Y.shape[0]  # 1次元配列の場合

"""HSV色空間にベクトル場の角度に色を、大きさに明度を対応させて表示"""
hsv = np.zeros((Y_shape, X_shape, 3), dtype='uint8')
hsv[..., 0] = cv2.normalize(any_ang, None, 0, 180, cv2.NORM_MINMAX)
hsv[..., 1] = 255
hsv[..., 2] = cv2.normalize(any_mag, None, 0, 255, cv2.NORM_MINMAX)
flow_rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)

"""ベクトル場の角度をカラーマップ表示"""
fig, ax = plt.subplots(figsize=(8, 8))
ax.imshow(flow_rgb, origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/68de183d-54d3-b78b-6300-94449324adda.png)

## HSV空間にベクトル場を任意の範囲の大きさに色相と明度を対応させて表示
```Python:HSV空間にベクトル場を任意の範囲の大きさに色相と明度を対応させて表示
"""サンプルのベクトル場"""
X = np.arange(-10, 11, 1, dtype=np.float64)
Y = np.arange(-10, 11, 1, dtype=np.float64)
U, V = np.meshgrid(X, Y)
mag, ang = cv2.cartToPolar(U, V, angleInDegrees=True)
any_mag, any_ang = any_size_only(mag, ang, 5, 10)
X_shape, Y_shape = X.shape[0], Y.shape[0]  # 1次元配列の場合

"""HSV色空間にベクトル場の大きさに色相と明度を対応させて表示"""
hsv = np.zeros((Y_shape, X_shape, 3), dtype='uint8')
hsv[..., 0] = cv2.normalize(any_mag, None, 0, 180, cv2.NORM_MINMAX)
hsv[..., 1] = 255
hsv[..., 2] = cv2.normalize(any_mag, None, 0, 255, cv2.NORM_MINMAX)
flow_rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)

"""ベクトル場の大きさをカラーマップ表示"""
fig, ax = plt.subplots(figsize=(10, 8))
ax.imshow(flow_rgb, origin='lower')
ax.quiver(np.arange(X_shape), np.arange(Y_shape), U, V, color='w')
ax, secax_x, secax_y = px2coord_axis(ax, X, Y)
secax_x.set_xlabel('X')
secax_y.set_ylabel('Y')
ax.set_aspect('equal')
plt.show()
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/e125969f-fbe7-d053-dd9f-4ce7926e0114.png)

</details>

# まとめ
ベクトル場の角度と大きさをカラー角度で表示する方法を紹介しました。ベクトル場は角度と大きさの2つの情報を一目で見たい場合が多いので、本記事が誰かのお役になれば幸いです。

# 参考資料
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.quiver.html

https://matplotlib.org/stable/gallery/images_contours_and_fields/quiver_simple_demo.html

https://matplotlib.org/stable/gallery/images_contours_and_fields/quiver_demo.html

https://docs.opencv.org/3.4/d4/dee/tutorial_optical_flow.html

https://docs.opencv.org/3.4/d2/de8/group__core__array.html#gac5f92f48ec32cacf5275969c33ee837d

https://en.wikipedia.org/wiki/HSL_and_HSV

https://matplotlib.org/stable/gallery/subplots_axes_and_figures/secondary_axis.html