OpenCV + Pythonで色空間を使用した画像セグメンテーション



Image Segmentation Using Color Space Opencv Python



OpenCV + Pythonで色空間を使用した画像セグメンテーション

色空間とは何ですか?

最も一般的な色空間RGB(赤、緑、青)では、色は赤、緑、および青のコンポーネントで表されます。より専門的な用語では、RGBは色を3つのコンポーネントのタプルとして説明します。各コンポーネントは0から255までの値を取ることができます。ここで、タプル(0、0、0)は黒を表し、(255、255、255)は白を表します。

RGBは、3つの原色の「加算」色空間と見なされます。黒地に赤、青、緑の光が大量に当たることで色が出ていると考えられます。



RGB値
ネット 255、0、0
オレンジ 255、128、0
ピンク 25,153,255

RGBは5つの主要な色空間モデルの1つであり、各モデルには多くのブランチがあります。さまざまな目的にさまざまな色空間を使用できるため、色空間が多すぎます。

印刷の分野では、CMYKは、白い背景から色を生成するために必要な色の組み合わせを記述するため、便利です。 RGBの0タプルは黒で、CMYKの0タプルは白です。当社のプリンターには、シアン、マゼンタ、イエロー、ブラックのインクタンクが含まれています。



HSVとHSLは、色相、彩度、明るさ/明るさの説明であり、画像のコントラストを識別するのに特に役立ちます。これらの色空間は、ソフトウェアの色選択ツールやWebデザインで一般的に使用されています。

実際、色は連続的な現象であり、色の数に制限はありません。ただし、色空間は離散構造(整数値の固定数)を介して色を表します。これは、人間の目と知覚も制限されているため、許容されます。色空間は、私たちが区別できるすべての色を完全に表すことができます。

OpenCVの色空間と画像の読み取り

まず、環境を設定する必要があります。この記事では、Python3.xがシステムにインストールされていることを前提としています。現在のOpenCVバージョンは3.xですが、インポートされるパッケージの名前はcv2のままであることに注意してください。



import cv2

OpenCVをインポートした後、OpenCVによって提供されるすべての色空間変換を表示し、それらをすべて変数に保存できます。

flags = [i for i in dir(cv2) if i.startswith('COLOR_')] # View the number of all color space conversions provided by OpenCV len(flags) # Find the index where COLOR_RGB2HSV is located flags.index('COLOR_RGB2HSV')

画像を表示するにはmatplotlib.pyplotが必要であり、一部の画像処理にはNumPyが必要です。 MatplotlibまたはNumPyがインストールされていない場合は、pip3 installmatplotlibおよびpip3installnumpyをインストールする必要があります。

import cv2 import matplotlib.pyplot as plt import numpy as np img = cv2.imread('nemo.jpg') # The default BGR format in cv, which needs to be converted to RGB in matplotlib to display images img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img) plt.show()

[、、(img-7B5X2hGj-1580710370547)(C: Users  67231  Desktop  ImageSegmentation  neo.jpg)]

RGB色空間でNemoを視覚化する

HSVは、色空間を色で割るのに適していますが、その理由を理解するために、ピクセルの色分布を視覚化して、RGB色空間とHSV色空間の画像を比較してみましょう。 3Dプロットはこれをよく示しており、各軸は色空間のチャネルを表しています。

#%% Draw a color 3D scatterplot import cv2 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # from matplotlib import cm from matplotlib import colors img = cv2.imread('nemo.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) r,g,b = cv2.split(img) fig = plt.figure(figsize=(8,6),dpi=80) axis = fig.add_subplot(1,1,1,projection='3d') # Pixel color settings pixel_colors = img.reshape((np.shape(img)[0]*np.shape(img)[1],3)) # print(pixel_colors) # Normalized norm = colors.Normalize(vmin=-1.,vmax=1.) norm.autoscale(pixel_colors) # Convert to list pixel_colors = norm(pixel_colors).tolist() # print('*'*20) # print(pixel_colors) # Display 3D scatterplot axis.scatter(r.flatten(),g.flatten(),b.flatten(),facecolors=pixel_colors,marker='.') axis.set_xlabel('Red') axis.set_ylabel('Green') axis.set_zlabel('Bule') plt.show()

結果:

[、、(img-nSbsCCr8-1580710370548)(C: Users  67231  Desktop  ImageSegmentation  rgb .png)]

この図からわかるように、画像のオレンジ色の部分は、赤、緑、青の値のほぼすべての範囲をカバーしています。 Nemoのさまざまな部分がグラフ全体に広がっているため、RGB値の範囲に従ってRGB空間でNemoをセグメント化することは容易ではありません。

HSV色空間でNemoを視覚化する

NemoをRGB空間で見たので、HSV空間でNemoを見て比較してみましょう。

前述のように、HSVは色相、彩度、明度(または明るさ)を表し、円柱状の色空間です。色または色相は、値チャネルを表す中央の垂直軸を中心に回転する角度寸法としてモデル化されます。値は、暗い(下部の0)から上部の明るいまでの範囲です。 3番目の軸は彩度です。これは、縦軸の最小彩度から中心から最も遠い最大彩度までの色相と影を定義します。

[、、(img-5lXiJRfD-1580710370549)(C: Users  67231  Desktop  ImageSegmentation  hsv.webp)]

#%% Images in HSV generate color 3D scatter plots import cv2 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # from matplotlib import cm from matplotlib import colors img = cv2.imread('nemo.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) hsv_img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) h,s,v = cv2.split(hsv_img) fig = plt.figure(figsize=(8,6),dpi=80) axis = fig.add_subplot(1,1,1,projection='3d') # Pixel color settings pixel_colors = img.reshape((np.shape(img)[0]*np.shape(img)[1],3)) # print(pixel_colors) # Normalized norm = colors.Normalize(vmin=-1.,vmax=1.) norm.autoscale(pixel_colors) # Convert to list pixel_colors = norm(pixel_colors).tolist() # print('*'*20) # print(pixel_colors) # Display 3D scatterplot axis.scatter(h.flatten(),s.flatten(),v.flatten(),facecolors=pixel_colors,marker='.') axis.set_xlabel('hue') axis.set_ylabel('saturation') axis.set_zlabel('value') plt.show()

結果:

[、、(img-rgMVvejq-1580710370549)(C: Users  67231  Desktop  ImageSegmentation  hsv .png)]

HSV空間では、Nemoのオレンジ色がより集中化され、視覚的に分離可能です。オレンジの彩度と値はさまざまですが、ほとんどの場合、色相軸に沿った狭い範囲内にあります。

色の範囲を選択してください

単純なオレンジ色のしきい値Nemoに従ってみましょう。上の写真を表示するか、オンラインで色を使用してアプリを選択できます( たとえば、RGBからHSVへのツール )範囲を選択します。ここで選択した見本は、明るいオレンジ色とほぼ濃い赤オレンジ色です。

import matplotlib.pyplot as plt from matplotlib.colors import hsv_to_rgb import numpy as np light_orange = (1,190,200) dark_orange = (18,255,255) lo_square = np.full((10,10,3),light_orange,dtype=np.uint8)/255. do_square = np.full((10,10,3),dark_orange,dtype=np.uint8)/255. plt.subplot(121) plt.imshow(hsv_to_rgb(do_square)) plt.subplot(122) plt.imshow(hsv_to_rgb(lo_square)) plt.show()

結果:

[、、(img-KAnED2NJ-1580710370549)(C: Users  67231  Desktop  ImageSegmentation  oarnge.png)]

同じ方法を使用して、白のしきい値を選択します

light_white = (0,0,200) dark_white = (145,60,255)
カラー画像を使用した画像セグメンテーション

適切な色の範囲を取得したら、cv2.inRange()を使用してNemoのしきい値を設定してみてください。 inRange()は、画像、低範囲、高範囲の3つのパラメーターを受け入れます。 ndarrayイメージのサイズのバイナリマスク(1と0)を返します。ここで、値1は範囲内の値を表し、値0は範囲外の値を表します。

import cv2 import matplotlib.pyplot as plt import numpy as np img = cv2.imread('nemo.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) hsv_img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) light_orange = (1,190,200) dark_orange = (18,255,255) light_white = (0,0,200) dark_white = (145,60,255) orange_mask = cv2.inRange(hsv_img,light_orange,dark_orange) white_mask = cv2.inRange(hsv_img,light_white,dark_white) mask = orange_mask+white_mask result = cv2.bitwise_and(img, img,mask=mask) plt.subplot(121) plt.imshow(mask,cmap='gray') plt.subplot(122) plt.imshow(result) plt.show()

結果:

[、、(img-wYk0W3U2-1580710370550)(C: Users  67231  Desktop  ImageSegmentation  1111111111111111111111111.png)]

結論として

このチュートリアルでは、いくつかの異なる色空間、RGBおよびHSV色空間で画像を配布する方法、およびOpenCVを使用して色空間間で変換して範囲を分割する方法について学習しました。

全体として、OpenCVの色空間を使用して画像内のオブジェクトのセグメンテーションを実行する方法を学び、他のタスクも実行できることを期待しています。このセグメンテーション手法は、シンプルで高速かつ信頼性があります。