#はじめに
カラー画像の色空間はBGR,RGBが通常ですが、RGB色空間だけでは処理が厳しい場合もあり、
その場合、HSV色空間を使ったりします。
HSV色空間を構成する色相(H),彩度(S),明度(V)がそれぞれどのように機能するのか?
それぞれ1つを変化させ、その画像を見たいと思います。
HSV色空間について、記事が少なかったので、ニーズがあるかどうかは
分かりませんが、書いてみようかと思いました。
OpenCVとPythonで行ってみたいと思います。
#行うこと
事前にOpenCVをインストールしておく必要があります。
読み込んだBGRカラー画像をHSV色空間に変換します。
H,S,Vを1つづつ変更し、画像を変更画像を作成、表示します。
##色相(H)の変更
HSVのHの変更は値を加算するのみです。
HSVのHは角度で循環するので、計算値がオーバーまたはアンダーした場合は
範囲におさまるように修正します。
範囲は0~255で、計算途中でfloat32に型変換を行います。
##彩度(S),明度(V)の変更
彩度(S),明度(V)は上下限があり、計算は共通changedSV()を使います。
S ← S × alpha + beta
V ← V × alpha + beta
##BGR-HSV色空間の変換
OpenCVのcvtColor()関数を使います。
オプションは、COLOR_BGR2HSV_FULL, COLOR_HSV2BGR_FULLと
...._FULLの付いたものを使います。
色相(H)の階調が180階調から256階調になるからです。
cvtColor()の詳細は下記をご覧ください。
docs.opencv.org - Color Space Conversions
#実行
##初期
import numpy as np
import cv2
# HSV S(彩度),V(明度)の変更
def changedSV(bgr_img, alpha, beta, color_idx):
hsvimage = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2HSV_FULL) # BGR->HSV
hsvf = hsvimage.astype(np.float32)
hsvf[:,:,color_idx] = np.clip(hsvf[:,:,1] * alpha+beta, 0, 255)
hsv8 = hsvf.astype(np.uint8)
return cv2.cvtColor(hsv8,cv2.COLOR_HSV2BGR_FULL)
bgr_img = cv2.imread('colorfull_tulips.jpg', cv2.IMREAD_COLOR)
まず、初期コードとしてこのようなコードを実行します。
changedSV()は、S(彩度),V(明度)変換共通のコードです。
##入力画像
読み込まれHSV色空間で処理される画像
このカラフルなチューリップ画像を用います。
##色相(H)の変更
###HSV 色相(H)の変更サンプルコード
# HSV H(色相)の変更
def changedH(bgr_img, shift):
hsvimage = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2HSV_FULL) # BGR->HSV
hi = hsvimage[:,:,0].astype(np.int32)
if shift < 0:
nhi = hi.flatten()
for px in nhi:
if px < 0:
px = 255 - px
nhi = nhi.reshape(hsvimage.shape[:2])
hi = nhi.astype(np.uint8)
chimg = (hi + shift) % 255
hsvimage[:,:,0] = chimg
hsv8 = hsvimage.astype(np.uint8)
return cv2.cvtColor(hsv8,cv2.COLOR_HSV2BGR_FULL) # HSV->BGR
# HSV S(彩度)の変更
image_h1 = changedH(bgr_img, 85)
image_h2 = changedH(bgr_img, -85)
色相(H)変更条件 120°(85) 加算
黄色(H=60°)のチューリップが、シアン色(H=180°)に変化しています。
色相(H)変更条件 -120°(-85) 加算
黄色(H=60°)のチューリップが、マゼンタ色(H=300°)に変化しています。
異世界の画像の様です。微妙なカメラ調整とか、特殊効果には使えますが、
マスク処理と組み合わせないと、なかなか使い道がなさそうです。
##彩度(S)の変更結果
###HSV 彩度(S)の変更サンプルコード
# HSV S(彩度)の変更
def changedS(bgr_img, alpha, beta):
return changedSV(bgr_img, alpha, beta, 1)
# HSV S(彩度)の変更
image_s1 = changedS(bgr_img, 2.0, -20)
image_s2 = changedS(bgr_img, 1/2, 20)
bgr_imgはBGR 24bitカラー画像です。
changedS()の返却値は変更されたBGR 24bitカラー画像です。
彩度(S)変更条件 alpha=2.0 beta=-20
彩度(S)を上げると色が濃くなりました。
彩度(S)変更条件 alpha=0.5 beta=20
彩度(S)を下げると色が薄くなります。
##明度(V)の変更
###HSV 明度(V)の変更サンプルコード
# HSV V(明度)の変更
def changedV(bgr_img, alpha, beta):
return changedSV(bgr_img, alpha, beta, 2)
# HSV V(明度)の変更
image_v1 = changedV(bgr_img, 1.8, 20)
image_v2 = changedV(bgr_img, 1/2, -50)
bgr_imgはBGR 24bitカラー画像です。
changedV()の返却値は変更されたBGR 24bitカラー画像です。
明度(V)変更条件 alpha=1.8 beta=20
明度を上げたら、画像が明るくなります。
明度(V)変更条件 alpha=0.5 beta=-50
明度を下げたら、画像が暗くなります。
#Pythonサンプルプログラム
import numpy as np
import cv2
# HSV H(色相)の変更
def changedH(bgr_img, shift):
hsvimage = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2HSV_FULL) # BGR->HSV
hi = hsvimage[:,:,0].astype(np.int32)
if shift < 0:
nhi = hi.flatten()
for px in nhi:
if px < 0:
px = 255 - px
nhi = nhi.reshape(hsvimage.shape[:2])
hi = nhi.astype(np.uint8)
chimg = (hi + shift) % 255
hsvimage[:,:,0] = chimg
hsv8 = hsvimage.astype(np.uint8)
return cv2.cvtColor(hsv8,cv2.COLOR_HSV2BGR_FULL) # HSV->BGR
# HSV S(彩度),V(明度)の変更
def changedSV(bgr_img, alpha, beta, color_idx):
hsvimage = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2HSV_FULL) # BGR->HSV
hsvf = hsvimage.astype(np.float32)
hsvf[:,:,color_idx] = np.clip(hsvf[:,:,1] * alpha+beta, 0, 255)
hsv8 = hsvf.astype(np.uint8)
return cv2.cvtColor(hsv8,cv2.COLOR_HSV2BGR_FULL)
# HSV S(彩度)の変更
def changedS(bgr_img, alpha, beta):
return changedSV(bgr_img, alpha, beta, 1)
# HSV V(明度)の変更
def changedV(bgr_img, alpha, beta):
return changedSV(bgr_img, alpha, beta, 2)
# 画像読み込み
bgr_img = cv2.imread('colorfull_tulips.jpg', cv2.IMREAD_COLOR)
# HSV S(彩度)の変更
image_h1 = changedH(bgr_img, 85)
image_h2 = changedH(bgr_img, -85)
# HSV S(彩度)の変更
image_s1 = changedS(bgr_img, 2.0, -20)
image_s2 = changedS(bgr_img, 1/2, 20)
# HSV V(明度)の変更
image_v1 = changedV(bgr_img, 1.8, 20)
image_v2 = changedV(bgr_img, 1/2, -50)
# 画像表示
cv2.imshow('original', bgr_img)
cv2.imshow('HSV h1', image_h1)
cv2.imshow('HSV h2', image_h2)
cv2.imshow('HSV s1', image_s1)
cv2.imshow('HSV s2', image_s2)
cv2.imshow('HSV v1', image_v1)
cv2.imshow('HSV v2', image_v2)
cv2.waitKey(0)
#動作環境
Windows10 Anaconda 3 (Miniforge)
Python 3.9.2 packaged by conda-forge
OpenCV 4.5.1
numpy 1.20.1
#さいごに
HSVについてはキーエンス XGシリーズの画像処理装置にもサポートされていたと
おもいます。産業分野でもカラー画像を処理することが増えてきていますので
BGR、RGB以外の色空間を知ることも必要になってくるかと思います。
さて、HSVの画像変化について、その変化を説明しなければと思って付けてみましたが、
あの程度の説明なら不要感がありますね。
お読みいただきありがとうございました。
#参考
Emotion Explorer - OpenCV 花の色を変えてみる。HSV色空間で色相を操作
Emotion Explorer - OpenCV HSV色空間で彩度、明度を変更