第12回 HSV表現

本題に入る前に、必ず 連絡 の動画を見てください。
Google Colabへのリンク

HSV表現と色立体

動画の解説を参照

ピクセルの色を表すには、いままで使っていたRGBの値を使う方法のほかに、色相、彩度、明度の3つの情報を使う方法 (HSV表現) があります。 これを下のような図で表わしたものを色立体とよび、この3つの座標で表わされる空間を色空間と言います。

今回は画像の色相・彩度・明度を変えてその結果を確認します。
そのために、以下の条件を満たす元画像が必要になります。 例えばこのような画像です。

元画像を決めたら、以降の変換の元になる画像変数「img」と、それをHSV形式に変換した変数「img_hsv」を作っておきます。
(この時点では読み込むだけで、画像は出力しません)
import cv2
import numpy as np
from google.colab import files

file = files.upload()
filename = next(iter(file))
img = cv2.imread(filename)
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

1. 色相の変更

動画の解説を参照

概要で述べたように、Hue (色相) はOpenCVでは 0~179 の値をとります。
ただし、一般的には色相は「1回転で元の色に戻る」このような図で表されます。
この図での時計回りの回転角 (0~359) は、OpenCVでいう Hue の値の2倍にあたります。

Hue の値を30ずつ増やすと、色がこのように変わります。
元画像の黄色い部分に注目すると、緑、シアン、青、マゼンタ、赤に変わっていることがわかります。

元画像
60°回転 (Hue += 30)
120°回転 (Hue += 60)
180°回転 (Hue += 90)
240°回転 (Hue += 120)
300°回転 (Hue += 150)
OpenCVで Hue の値を増やす処理はこのようになります。
img1[:, :, 0] = (img1[:, :, 0] + dh) % 180
「% 180」は、Hue の値の範囲が 0~179 なので、その範囲がらはみ出したときに範囲内に収まるようにするための処理です。
(たとえば 175 → 175 + 30 = 205 → 25)
dhs = [30, 60, 90, 120, 150]
for dh in dhs:
  img1 = img_hsv.copy()
  img1[:, :, 0] = (img1[:, :, 0] + dh) % 180
  img1 = cv2.cvtColor(img1, cv2.COLOR_HSV2BGR)
  cv2.imwrite('ex1_' + format(dh * 2, '03') + '.jpg', img1)

課題1

元画像の色相を60~300°回転させた画像 ex1_060.jpg~ex1_300.jpg を出力してください。

2. 彩度の変更

動画の解説を参照

彩度は鮮やかさを表す値なので、小さくすればくすんだ色になり、大きくすれば鮮やかになります。
色立体ではそれぞれ中心側への移動、外側への移動に対応します。

元画像
彩度下げ
(Saturation -= 100)
彩度上げ
(Saturation += 100)
OpenCVでの彩度の範囲は 0~255 なので、値を変更したあとで clip関数で範囲内に収まるように修正します。
img2[:, :, 1] = np.clip(img2[:, :, 1] + ds, 0, 255)
ただし、clip関数を使うためには値の形式を float32型にする必要があるので、彩度を変える前に
img2 = img2.astype(np.float32)
で型を変え、処理後に
img2 = img2.astype(np.uint8)
で元の型に戻します。
dss = [-100, 100]
for ds in dss:
  img2 = img_hsv.copy()
  img2 = img2.astype(np.float32)
  img2[:, :, 1] = np.clip(img2[:, :, 1] + ds, 0, 255)
  img2 = img2.astype(np.uint8)
  img2 = cv2.cvtColor(img2, cv2.COLOR_HSV2BGR)
  cv2.imwrite('ex2_' + str(ds) + '.jpg', img2)

課題2

元画像の彩度を100増減させた画像 ex2_-100.jpg, ex2_100.jpg を出力してください。

3. 明度の変更

動画の解説を参照

明度は明るさを表す値なので、小さくすれば暗くなり、大きくすれば明るくなります。
色立体ではそれぞれ下への移動、上への移動に対応します。

元画像
明度下げ
(Value -= 100)
明度上げ
(Value += 100)
OpenCVでの明度の範囲は 0~255 なので、値を変更したあとで clip関数で範囲内に収まるように修正します。
(彩度の変更のときと同様に、この処理の前後で型の変更を行います)
img3[:, :, 2] = np.clip(img3[:, :, 2] + dv, 0, 255)

dvs = [-100, 100]
for dv in dvs:
  img3 = img_hsv.copy()
  img3 = img3.astype(np.float32)
  img3[:, :, 2] = np.clip(img3[:, :, 2] + dv, 0, 255)
  img3 = img3.astype(np.uint8)
  img3 = cv2.cvtColor(img3, cv2.COLOR_HSV2BGR)
  cv2.imwrite('ex3_' + str(dv) + '.jpg', img3)

課題3

元画像の明度を100増減させた画像 ex3_-100.jpg, ex3_100.jpg を出力してください。

提出

動画の解説を参照

今回作成したノートブックを「imgprc2024@gmail.com」と共有してください。
※ 第2回で共有した、画像共有用の「画像処理」フォルダの中に「第12回」フォルダを作り、その中に今回の元画像と出力画像を入れてください。
※ 課題の再提出の際は、ノートブックの再度の共有はせずにチャットで連絡してください。