Pythonにて、HSV色空間の色相(Hue)の平均値を算出する方法を紹介します!
おすすめの読者
- 色相(Hue)の平均値を算出する設計を知りたい方
- 色相(Hue)の平均値を算出する実装を知りたい方
- 色相(Hue)の平均値を算出結果を知りたい方
【結論】色相(Hue)の平均値を算出する方法
結論、色相(Hue)の平均値を算出するため、色相環・ベクトルととらえることで、平均計算を実現します!
本記事の内容を深く理解するためには、 詳解 OpenCV 3 ―コンピュータビジョンライブラリを使った画像処理・認識
がおすすめです!
色相の平均値を算出する方法
- Hueの画素をベクトル化する
- 全画素のベクトル平均を算出する
- 平均ベクトルを色相の平均値として返す
色相の平均値を算出するためのコードはこちらです。
import numpy as np
def calculate_average_hue(hue_image: np.ndarray) -> float:
if (0 > np.min(hue_image)) or (np.max(hue_image) > 179):
raise ValueError("入力するHue画像は0~179を入力してください")
# OpencvのHueの範囲は0~180であるため、0~360に拡張
hue_image_0_to_360 = hue_image * 2
# X, Y方向にそれぞれベクトル化
hue_vec_x = np.cos(np.deg2rad(hue_image_0_to_360))
hue_vec_y = np.sin(np.deg2rad(hue_image_0_to_360))
# X, Y方向それぞれベクトルを平均化
hue_vec_x_ave = np.average(hue_vec_x)
hue_vec_y_ave = np.average(hue_vec_y)
# ベクトルのarctanを算出
average_hue_vec_arctan_deg = np.rad2deg(
np.arctan2(hue_vec_y_ave, hue_vec_x_ave))
# np.arctan2の出力範囲は-180deg~180degであるため、0~360degに変換
if average_hue_vec_arctan_deg < 0:
average_hue_vec_arctan_deg += 360
# OpencvのHueの範囲である0~180に合わせる
average_hue_vec_arctan2_deg_0_to_180 = average_hue_vec_arctan_deg / 2.
return average_hue_vec_arctan2_deg_0_to_180
【設計】色相(Hue)の平均値を算出する考え方
色相を「環」として考える
色相(Hue)は下記のように「色相環」として捉えることができます。
この性質を活用し、色相の平均値算出を行います。
色相をベクトル演算として解く
色相をベクトルとして定義することで、色相環上の計算として求めることができるようになります。
OpenCVのHueの範囲に注意する
OpenCVのHue成分は、0~179の範囲で表現されます。
そのため、実装上は0~360 [deg] の範囲で演算するように前処理・後処理を行う必要があります。
Note For HSV, Hue range is [0,179], Saturation range is [0,255] and Value range is [0,255]. Different softwares use different scales. So if you are comparing OpenCV values with them, you need to normalize these ranges.
Changing Colorspaces
【実装】色相(Hue)の平均値をPythonで算出する
実装例
下記コードによって、色相の平均値を算出することができます!
import numpy as np
def calculate_average_hue(hue_image: np.ndarray) -> float:
if (0 > np.min(hue_image)) or (np.max(hue_image) > 179):
raise ValueError("入力するHue画像は0~179を入力してください")
# OpencvのHueの範囲は0~180であるため、0~360に拡張
hue_image_0_to_360 = hue_image * 2
# X, Y方向にそれぞれベクトル化
hue_vec_x = np.cos(np.deg2rad(hue_image_0_to_360))
hue_vec_y = np.sin(np.deg2rad(hue_image_0_to_360))
# X, Y方向それぞれベクトルを平均化
hue_vec_x_ave = np.average(hue_vec_x)
hue_vec_y_ave = np.average(hue_vec_y)
# ベクトルのarctanを算出
average_hue_vec_arctan_deg = np.rad2deg(
np.arctan2(hue_vec_y_ave, hue_vec_x_ave))
# np.arctan2の出力範囲は-180deg~180degであるため、0~360degに変換
if average_hue_vec_arctan_deg < 0:
average_hue_vec_arctan_deg += 360
# OpencvのHueの範囲である0~180に合わせる
average_hue_vec_arctan2_deg_0_to_180 = average_hue_vec_arctan_deg / 2.
return average_hue_vec_arctan2_deg_0_to_180
動作確認
単純な「1x2」の配列での動作確認
>>> print("[0, 0]の色相平均:", calculate_average_hue(np.array([0, 0])))
[0, 30]の色相平均: 0.0
>>> print("[0, 30]の色相平均:", calculate_average_hue(np.array([0, 30])))
[0, 30]の色相平均: 14.999999999999998
>>> print("[0, 90]の色相平均:", calculate_average_hue(np.array([0, 90])))
[0, 90]の色相平均: 45.0
>>> print("[0, 91]の色相平均:", calculate_average_hue(np.array([0, 91])))
[0, 91]の色相平均: 135.49999999999997
>>> print("[0, 100]の色相平均:", calculate_average_hue(np.array([0, 100])))
[0, 100]の色相平均: 140.0
>>> print("[0, 170]の色相平均:", calculate_average_hue(np.array([0, 170])))
[0, 170]の色相平均: 175.0
>>> print("[0, 179]の色相平均:", calculate_average_hue(np.array([0, 179])))
[0, 179]の色相平均: 179.5
>>> print("[90, 90]の色相平均:", calculate_average_hue(np.array([90, 90])))
[90, 90]の色相平均: 90.0
>>> print("[90, 91]の色相平均:", calculate_average_hue(np.array([90, 91])))
[90, 91]の色相平均: 90.5
>>> print("[90, 170]の色相平均:", calculate_average_hue(np.array([90, 170])))
[90, 170]の色相平均: 130.0
>>> print("[90, 179]の色相平均:", calculate_average_hue(np.array([90, 179])))
[90, 179]の色相平均: 134.50000000000003
>>> print("[90, 1]の色相平均:", calculate_average_hue(np.array([90, 1])))
[90, 1]の色相平均: 45.49999999999997
lennaでの動作確認
>>> import cv2
>>> # lennaの画像は`http://www.lenna.org/len_std.jpg`より取得
>>> bgr_image = cv2.imread("len_std.jpg", cv2.IMREAD_UNCHANGED)
>>> hue_image = cv2.split(cv2.cvtColor(bgr_image, cv2.COLOR_BGR2HSV))[0]
>>> calculate_average_hue(hue_image)
24.453125
【まとめ】色相(Hue)の平均値を算出する方法
結論、データ構造管理にはJSONスキーマを活用すべきです! 詳解 OpenCV 3 ―コンピュータビジョンライブラリを使った画像処理・認識
本記事の内容を深く理解するためには、 がおすすめです!
色相の平均値を算出する方法
- Hueの画素をベクトル化する
- 全画素のベクトル平均を算出する
- 平均ベクトルを色相の平均値として返す
本日紹介したコードのスニペットは以下に公開しています!