【Python】OpenCVの色空間の変換を一通り試してみた。

▼この記事をSNSでシェアする▼

スポンサーリンク

スポンサーリンク

トンビ
色空間むずいなにいってるかわからん

最近Djangoで画像を色々変換して、表示・ダウンロードしてくれるサイトを製作中です。

OpenCVのドキュメントとかネットとかみてもよくわからないところがあったので、今回一通り実際にコードを書いて試してみた。

事前設定

Anacondaをインストールし、opencv-pythonをpip installしておけば実行できます

概要

OpenCVをインストールすると、import cv2と書くことでcv2.メソッド()の形で画像や動画を扱う関数がたくさん使えるようになります。

今回の色空間の変換では、

cv2.cvtColor(画像ファイル,色空間の変換の定数)

のメソッドを使い変換します。

OpenCVの公式のドキュメントを見ると詳細がいろいろかいてあります。

ただ色空間については、あまり詳しく書いていないです。

OpenCVでは標準の色空間でBGRとなっている。(RGBではないので注意)

今回は基準となるBGRからHSVなどといった他の色空間へと変更していく。

BGRでの色の扱い

OpenCVをPythonで取り扱う際に、numpyの3次元の配列として画像を扱う。

PillowのPIL.Imageからndarrayに変換した場合はRGBで読み込まれるが、OpenCVだとBGRです。

横(width)のpx、縦(height)のpxの画素の場所ごとに、BGRの色の値(0~255)をとる。

BGRはOpenCVで標準の色空間でこの犬の画像は

今回比較基準となる画像です。ぜひ下の画像とどう違うのかを見比べる参考にしてください。

色空間の変換

GRAY(グレースケール)

黒(0)~白(255)の一次元で表現されています。

BGRの値に以下の式を適用することで、白黒の値を求め2次元のデータに変化させています。

Y=0.299R+0.587G+0.114B

次に出てくるが、このグレースケールの変換は非常に画像認識でよく使う色空間であり、色彩溢れる画像から余分な情報を取り除き、物体の輪郭や形状を取り出しすのに扱いやすい画像となる。

GRAY(モノクロ)

これは特定の色空間の変換ではないのですが、グレースケールに変換した後に、色の値が150以上の箇所を白(255)に、150未満の箇所を黒(0)に変換した画像であり、閾値変換をしたモノクロ画像です。

HSV

  • h(0~360):色相(色彩を表すパラメータ)、h=0(赤),120(緑),225(青)などなど

Rが最大値の場合 色相 H = 60 × ((G – B) ÷ (R – G,Bの最小値))
Gが最大値の場合 色相 H = 60 × ((B – R) ÷ (G – R,Bの最小値)) +120
Bが最大値の場合 色相 H = 60 × ((R – G) ÷ (B – R,Gの最小値)) +240
3つとも同じ値の場合 色相 H = 0

  • s(0~255):彩度=(R,G,Bの最大値 – R,G,Bの最小値) ÷ R,G,Bの最大値
  • v(0~255):明度 V = R,G,Bのうち最大値が反映される

→画像がやたら明るくなる

変換してその画像そのものを使うことが少ないですが、特定の色の箇所のみに処理をしたい場合に有用です。

hの値域を指定して、条件に当てはまる元の画素を処理することが多い。

HLS

HSVを改良して明るさを考慮した色空間がHLS(HSL)

  • h(0~360):色相(色彩を表すパラメータ)、h=0(赤),120(緑),225(青)などなど

Rが最大値の場合 色相 H = 60 × ((G – B) ÷ (R – G,Bの最小値))
Gが最大値の場合 色相 H = 60 × ((B – R) ÷ (G – R,Bの最小値)) +120
Bが最大値の場合 色相 H = 60 × ((R – G) ÷ (B – R,Gの最小値)) +240
3つとも同じ値の場合 色相 H = 0

  • l(0~255):輝度

(R,G,Bの最大値 +R,G,Bの最小値) ÷ 2

  • s(0~255):彩度

収束値 CNT = (RGBの最大値 +R,G,Bの最小値) ÷ 2
収束値 CNTが127以下の場合 彩度 S = (R,G,Bの最大値 -R,G,Bの最小値) ÷ (RGBの最大値 +R,G,Bの最小値)
収束値 CNTが128以上の場合 彩度 S = (R,G,Bの最大値 -R,G,Bの最小値) ÷ (510 -RGBの最大値 -R,G,Bの最小値)

XYZ

これが難解

下記リンクに専門的な話は委ねます。

XYZh表現体系とは

人の目に見えないRGB以外の色を表現すべく、表色や目の波長感度特性を詳しく調べて数値化した “表色上の3原色”をXYZと呼ぶそうです。

計算式は以下の通り

X = 0.4124R + 0.3576G + 0.1805B
Y = 0.2126R + 0.7152G + 0.0722B
Z = 0.0193R + 0.1192G + 0.9505B

YCrCb

Y(濃淡信号)とCr,Cb(色差信号)を用いた色体系

Y = 0.299R+0.587G+0.114B

Cr =0.713 (R-Y) + delta

Cb =0.564 (B-Y) + delta

8bitイメージ: delta=128

16bitイメージ: delta=32768

浮動小数点型のイメージ: delta=0.5

Luv

XYZ色空間をより簡単に計算に用いるため色差の均一性を保つことを目的に作られた

計算式は以下の通り、XYZの値をあらかじめ求めそれを変換する

\(Y \gt 0.08856\)の場合

L= \(116Y^{1/3}\)

\(Y \leq 0.08856\)の場合

L= 903.3Y

\(u’ = \frac{4Y}{X+15Y+3Z}\)

\(v’ = \frac{9Y}{X+15Y+3Z}\)

u=13L*(u’-un)     ※un=0.19793943

v=13L*(v’-vn)      ※vn=0.46831096

Lab

XYZよりもできるだけ人間の感覚に近い均等な色空間として考案されたのが Lab 表色系

計算式は以下の通り、XYZの値をあらかじめ求めそれを変換する

X=\(\frac{X}{Xn}\)             ※Xn=0.950456

Z=\(\frac{Z}{Zn}\)             ※Zn=1.088754

\(Y \gt 0.08856\)の場合

L= \(116Y^{1/3}-16\)

f(t) = \(t^{1/3}\)

\(Y \leq 0.08856\)の場合

L= 903.3Y

f(t) = 7.787t + \(\frac{16}{116}\)

a=500(f(X)-f(Y)) + delta

b=200(f(Y)-f(Z)) + delta

8bitイメージ: delta=128

16bitイメージ: サポートなし

浮動小数点型のイメージ: delta=0

RGB

この変換ではBGRで読み込んだデータがRGBに変換されている

青の数値が赤に、赤の数値が青に転置されている。

そのため首輪の部分が青になり、緑色の部分はあまり変化がない

まとめ

OpenCV便利ですね、ただネットの情報がそこまで多くないのが残念

無知な僕にはマイナーな色空間は活用法がいまいち・・・

HSVとグレースケールがわかっていればいいような気がする。

参考サイト

スポンサーリンク


関連記事

▼この記事をSNSでシェアする▼

フォローする

メニュー・主な記事カテゴリ

おすすめ特集!




「ゆとり鳥日記」について
ITを中心に関心の赴くままに好きなように書いていく雑記ブログ!管理人が二人います。
◆フクロウ(19卒就活生)
◆トンビ(社会人1年目SE)

詳しいプロフィール
お仕事の依頼・ご要望

ゆとり鳥日記をBTCで応援する