OpenCVでのHSV色空間lower,upperの取り扱い

HSVはlower,upperで色選択できるのがメリットなんだけども、色に対するlower,upperが不明で苦労したのでメモする。

#HSVとは

rgbの拡張みたいもんで、色相(Hue)、彩度(Saturation・Chroma)、明度で構成される。何が嬉しいのかというと色を範囲指定しやすいというメリットがある。
Hの部分はrgbの部分にあたる。

色相 - 色の種類　　0 - 360の範囲
彩度 - 色の鮮やかさ　　0 - 100 % の範囲。
明度 - 色の明るさ　　0 - 100 % の範囲。

で設定する数値はソフトによって変わるそうだ。opencvだと明度とか100から255の間なんだと思う。

![スクリーンショット 2017-07-05 21.53.25.png](https://qiita-image-store.s3.amazonaws.com/0/64334/f8a79cf2-26a0-3bb5-fadc-ff53994a70a4.png)

wiki参照
https://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93

シミュレーター
http://www.rapidtables.com/convert/color/hsv-to-rgb.htm


#RGBからlower,upperにコンバートする

```py:convert.py
import sys
import numpy as np
import cv2
 
#rgb
red = sys.argv[1]
green = sys.argv[2]
blue = sys.argv[3]  
 
color = np.uint8([[[blue, green, red]]])
hsv_color = cv2.cvtColor(color, cv2.COLOR_BGR2HSV)
 
hue = hsv_color[0][0][0]
 
print("Lower bound is :"),
print("[" + str(hue-10) + ", 100, 100]\n")
 
print("Upper bound is :"),
print("[" + str(hue + 10) + ", 255, 255]")

```


```
python convert.py 255 255 255
```

こんな感じで変換するんだけども、こいつはざっくりでしかコンバートできてない。


#HSVのlower,upperをデバッグする

```py:hsv.py
import cv2
import numpy as np

image_hsv = None   # global ;(
pixel = (20,60,80) # some stupid default

# mouse callback function
def pick_color(event,x,y,flags,param):
    if event == cv2.EVENT_LBUTTONDOWN:
        pixel = image_hsv[y,x]

        #you might want to adjust the ranges(+-10, etc):
        upper =  np.array([pixel[0] + 10, pixel[1] + 10, pixel[2] + 40])
        lower =  np.array([pixel[0] - 10, pixel[1] - 10, pixel[2] - 40])
        print(pixel, lower, upper)

        image_mask = cv2.inRange(image_hsv,lower,upper)
        cv2.imshow("mask",image_mask)

def main():
    import sys
    global image_hsv, pixel # so we can use it in mouse callback

    image_src = cv2.imread(sys.argv[1])  # pick.py my.png
    if image_src is None:
        print ("the image read is None............")
        return
    cv2.imshow("bgr",image_src)

    ## NEW ##
    cv2.namedWindow('hsv')
    cv2.setMouseCallback('hsv', pick_color)

    # now click into the hsv img , and look at values:
    image_hsv = cv2.cvtColor(image_src,cv2.COLOR_BGR2HSV)
    cv2.imshow("hsv",image_hsv)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__=='__main__':
    main()
```


```
python hsv.py hoge.png
```

起動してhsvの画面でダブルクリックするとマスクされる。
例えば黄色と緑は非常に似ている。
ピンクと赤も。この場合ピンクをクリックしてるのに赤も反応したりする。
つまり色の濃さと明るさを微調整しないといけない。
自動のやり方は不明だったので手動でいじった。

#手動でHSVを調整する。


```py:hsv_sample.py
import sys
import cv2
import numpy as np

import sys
import cv2
import numpy as np
#yellow
# lower =  np.array([30,100,250])
# upper =  np.array([40,255,255])
#pink
lower =  np.array([160,50,50])
upper =  np.array([180,255,255])
#yellowgreen
# lower =  np.array([30,100,200])
# upper =  np.array([60,255,250])

image_src = cv2.imread(sys.argv[1])
image_src = cv2.cvtColor(image_src,cv2.COLOR_BGR2HSV)
image_src = cv2.inRange(image_src,lower,upper)

while True:
    cv2.imshow("image_src",image_src)

    if cv2.waitKey(10) == 27: # ESC
        break
```

非常に原始的な方法ではあるが、yellowと非常に似ているyellowgreenのマスクもうまくいった。


#やってないけども。。。

こんなので表示して、チョット範囲指定すれば自動化もできたのかもしれない。


```py:
>>> green = np.uint8([[[0,255,0 ]]])
>>> hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
>>> print( hsv_green )
[[[ 60 255 255]]]
```

#参考

How to define the “lower” and “upper” range of a color?
http://answers.opencv.org/question/134248/how-to-define-the-lower-and-upper-range-of-a-color/
http://docs.opencv.org/trunk/df/d9d/tutorial_py_colorspaces.html