LoginSignup
5
5

More than 3 years have passed since last update.

OpenCV 画像の色味をHSVで変更してみる。

Posted at

はじめに

カラー画像の色空間はBGR,RGBが通常ですが、RGB色空間だけでは処理が厳しい場合もあり、
その場合、HSV色空間を使ったりします。

HSVカラーリング
HSV_カラーリング.png

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色空間で処理される画像
colorfull_tulips.jpg
このカラフルなチューリップ画像を用います。

色相(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) 加算
HSV_h1.jpg
黄色(H=60°)のチューリップが、シアン色(H=180°)に変化しています。

色相(H)変更条件 -120°(-85) 加算
HSV_h2.jpg
黄色(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
HSV_s1.jpg
彩度(S)を上げると色が濃くなりました。

彩度(S)変更条件 alpha=0.5 beta=20
HSV_s2.jpg
彩度(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
HSV_v1.jpg
明度を上げたら、画像が明るくなります。

明度(V)変更条件 alpha=0.5 beta=-50
HSV_v2.jpg
明度を下げたら、画像が暗くなります。

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色空間で彩度、明度を変更

写真引用

「カラフルチューリップ」 photoAC掲載 リトルマロンさんの写真

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5