記事ディレクトリ
この列のコードアドレス
https://github.com/xiawei20161308104/xv_opencv_tutorials
このセクションのコードパスxv_opencv_tutorials/ImageProcessinginOpenCV/changing_colorspaces.py
参照图像工程第4版,张毓晋,清华大学出版社
0. このセクションに関係する新しい opencv 関数
- 色空間変換機能
cv.cvtColor()
1.色の形成
“Indeed rays,properly expressed,are not colored”——牛顿。
光は異なる周波数の電磁波です。人間の視覚は光の刺激を感じ、異なる周波数の電磁波を異なる色として認識します。したがって、色は人間の目と脳にのみ存在し、物理世界には異なる放射線が分布しています。 。
2. 色空間
カラーモデルは色空間に基づいて構築されており、カラーモデルと色空間の概念は区別されません。
原則に従って4つのカテゴリに分類でき、用途に従って2つのカテゴリに分類できます
原理モデルによると | 原理 | 例 |
---|---|---|
測色モデル/色度モデル | 分光反射率の物理測定に基づく | 色の「id」については、色の最も正確な表現 |
生理学的モデル | 人間の網膜に存在する 3 つの基本的な色知覚錐体に基づいています | RGB |
精神物理学モデル / 精神物理学モデル | 人間の色の認識に基づく | HSI、HCV、L*a*b* |
反対のモデル | 知覚実験に基づく | HSB |
アプリケーションモデルに応じて | 応用 | 例 |
---|---|---|
ハードウェア用 | モニター、プリンター | RGB、CMY、CMYK |
視覚指向 | アニメーション、画像処理 | HSI、HSB、L*a*b* |
3. 適切な色空間を選択する必要がある理由
人間の色の知覚は、網膜を刺激する電磁放射線のスペクトル エネルギー分布、人間の神経心理学、および人間の生理学的行動に関連しており、色の知覚は非常に複雑なプロセスであり、その応用も多岐にわたります。CIE は多数のカラー モデルを定義しています。各モデルは特定の状況にのみ適用でき、
すべての状況を満たすことができる一般的なモデルはありません。色の原則と色の用途に基づいて適切なカラー モデルを選択することで、問題の次元を統一できます。
4. 適切な色空間を選択する方法
ニーズを理解し、対応する特性を持つ色空間を見つけてください。たとえば、RGB モデルは、画像取得入力や画像出力表示などのアプリケーションに特に適していますが、人間の視覚認識とは多少異なります。つまり、画像を見たときに、その赤、緑成分と青成分は を持ち、現時点では HSV モデルの方が適しており、H は色相を表し、S は彩度を表し、V は強度を表し、このようにして確立されたモデルは人間の知覚と高い互換性があります。
HSV モードで画像を分析し、画像の V 値を取得し、それを 100 ピクセル縮小して v1 にし、比較して観察すると、人間の目は明るさの変化を明確に認識できることがわかります。
def main():
# 读取图像
src = cv.imread("../imgs/opencv.png")
# 转换HSV空间
hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV)
# 分离通道
h, s, v = cv.split(hsv)
cv.namedWindow("v", cv.WINDOW_NORMAL)
cv.imshow("v", v)
# 减小亮度
v1 = v - 30
cv.namedWindow("v1", cv.WINDOW_NORMAL)
cv.imshow("v1", v1)
cv.waitKey(0)
cv.destroyAllWindows()
5. 一般的に使用される色空間
RGB
(画像工学第 4 版、張裕仁、清華大学出版部より)
- 人間の錐体細胞に基づいた、人間の視覚系の構造と密接に関連したモデル
- 網膜の 3 つの異なる色を感知する錐体細胞の波長応答曲線 SML は、基本的に 3 原色 RGB に対応します。
- RGB モデルはデカルト座標系で確立されます
- 原点は黒、原点から最も遠い頂点は白、これら 2 点を結ぶ線は異なる色合いのグレーです。
CMY
- 3色の光を2つ重ね合わせて三補色CMYを作ります。Cは青緑(緑+青)、Mはマゼンタ(赤+青)、Yはイエロー(赤+緑)です。
- 一般的に出版社の印刷に使用されますが、画像処理は一般的には使用されません
HSI
- HSIは人間の知覚に対応しており、ユーザー指向のカラーモデルと呼ばれます。
- 色相、彩度、強度で色を表現する
- ディスプレイに依存しない
- HSI の利点:
- 強度成分は画像の色情報とは何の関係もなく独立しています。つまり、強度/明るさ成分の変換は画像の色相や彩度を変更しません。
- H と S は独立しており、人間の感覚に適応するため、HSI モデルは人間の視覚システムに基づいて色知覚特性を処理および分析する画像アルゴリズムに非常に適しています。
- HSI の欠点:
- これは均一な色空間モデルではありません。人間が知覚する 2 点間の色の違いの程度は、色空間内の 2 点間のユークリッド距離に対応します。
HSI カラー モデルの人間の感覚への適応をより直観的に体験するために、コードは同じ画像の RGB コンポーネントと HSV コンポーネントを分割します。
色が濃いほど、成分値の割合が大きくなります。見てわかるように、HSI の 3 つのプロットはまったく異なって見えます人眼能感觉到的HSI三个分量的区别要比RGB三个分量的区别要大
。
ラ*ア*ブ*
- 人間の直感の観点から、カラーモデルによる色の記述は、人間の色の知覚、つまり
L\*a\*b\*是一个均匀彩色空间
人間が知覚する 2 点間の色の違いの程度と、この 2 点間のユークリッド距離とできるだけ同期する必要があります。スペース対応 - また、人間の視覚のための色空間でもあり、機器とは関係がなく、自然光に近い用途に適しています。
6.色空間の計算式を変換する
各ツールキット ツールによって定義されるコンポーネントの範囲は異なります。たとえば、色相 H は 0 ~ 180 または 0 ~ 360 であり、数学的には相互に変換できます。そのため、opencv の処理中、8 ビットおよび 16 ビットのイメージの場合、R、G、B は浮動小数点形式に変換され、0 ~ 1 にスケーリングおよび正規化されます。
変換式の一部は次のとおりです。
- RGB2グレー
-
RGB2CIE XYZ
-
RGB2HSV
7.opencv 変換色空間コード + コメント + エフェクト
opencv の cvtColor 関数は色空間の変換を実現し、150种
色空間の変換方法を提供し、cvtColor
関数のflag
位置に対応する変換識別子を埋めるだけで済みます。変換IDは以下のように取得します。
import cv2 as cv
flags = [i for i in dir(cv) if i.startswith('COLOR_')]
#这里会输出150种flag,他们是opencv定义的彩色空间转换flag,是cv.cvtColor(input_image, flag)的第二个参数值。
print( flags )
上記のコードを通じて自分で取得することも、公式ドキュメントを直接問い合わせることもできます
ここでは、変換コードと効果の 2 つのケースを示します。つまり、BGR2Gray
とBGR2HSV
(HSI は opencv では提供されていませんが、これら 2 つの色空間は似ています)
#BGR2Gray
import cv2 as cv
def main():
src = cv.imread("../imgs/opencv.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.imwrite('gray.png', gray)
cv.imshow("gray", gray)
cv.waitKey(0)
cv.destroyAllWindows()
if __name__ == "__main__":
main()
def main():
src = cv.imread("../imgs/opencv.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV)
cv.imwrite('hsv.png', hsv)
cv.imshow("hsv", hsv)
# 分离通道
h, s, v = cv.split(hsv)
cv.namedWindow("h", cv.WINDOW_NORMAL)
cv.imshow("h", h)
cv.namedWindow("s", cv.WINDOW_NORMAL)
cv.imshow("s", s)
cv.namedWindow("v", cv.WINDOW_NORMAL)
cv.imshow("v", v)
cv.waitKey(0)
cv.destroyAllWindows()
if __name__ == "__main__":
main()