당신은 주제를 찾고 있습니까 “opencv hsv 색상 표 – OpenCV Python 강좌 – 5. HSV 색공간에서 특정색 검출하기“? 다음 카테고리의 웹사이트 you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: you.tfvp.org/blog. 바로 아래에서 답을 찾을 수 있습니다. 작성자 멈춤보단 천천히라도 이(가) 작성한 기사에는 조회수 11,688회 및 좋아요 102개 개의 좋아요가 있습니다.
opencv hsv 색상 표 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 OpenCV Python 강좌 – 5. HSV 색공간에서 특정색 검출하기 – opencv hsv 색상 표 주제에 대한 세부정보를 참조하세요
안녕하세요 ^^. 이번 영상에서는 HSV 공간에서 특정색을 검출하는 방법을 설명합니다.
영상에서 작성한 코드는 다음 링크에 있습니다.
https://github.com/webnautes/nudapeu/blob/master/opencv-python-0051.py
https://github.com/webnautes/nudapeu/blob/master/opencv-python-0052.py
도움이 되었으면 좋아요와 구독을 해주세요.
감사합니다.
OpenCV 공부하실때 다음 책을 추천합니다.
알짜배기 예제로 배우는 OpenCV
http://www.yes24.com/Product/Goods/90071418
Python과 C++로 작성된 풍부한 예제가 포함되어 있습니다.
블로그 : http://webnautes.tistory.com
음악 출처: https://www.bensound.com
opencv hsv 색상 표 주제에 대한 자세한 내용은 여기를 참조하세요.
HSV 이미지를 사용하여 특정 색상 Object 추출하기
– OpenCV에서 색조 범위는 0~180이므로 원하는 색상을 얻으려면 HSV 색상표 값에서 1/2 해줘야 한다. ※ 오렌지 색과 초록색은 색상표와 일치했는데 파란색 …
Source: bradbury.tistory.com
Date Published: 3/11/2021
View: 8737
opencv 입문하기 7-2편 HSV, 특정 색상 추출(inRange)
HSV 색 공간 또는 HSV 모델은 색을 표현하는 하나의 방법이자, 그 방법에 따라 색을 배치하는 방식이다. 색상(Hue), 채도(Saturation), 명도(Value)의 …
Source: sikaleo.tistory.com
Date Published: 6/6/2022
View: 4084
[OPENCV] 5. 색 공간 모델 HSV – 평화지키미
1. HSV란? ○ 2. OPENCV의 HSV함수. ○ 3. 코드 작성. ○ 4. 심화 … 그에 비해 HSV 색 공간은 색을 혼합할 수록 밝아지는 가산혼합과 혼합할 수록 …
Source: 95mkr.tistory.com
Date Published: 6/4/2021
View: 4587
OpenCV | Python | HSV 색공간에서 이미지의 특정색 추출하기
우선 색공간이란 색을 표현하는 방법을 3차원 좌표계로 표현한 것이다. 그 중 RGB 와 HSV 색공간이 존재한다.먼저 RGB 는 빛의 삼원색인 빨강, 초록, …
Source: velog.io
Date Published: 6/19/2021
View: 8616
Opencv 파이썬 Colab – Hsv로 변환 및 원하는 색상 부분 추출하기
… opencv hsv 색상 표:.
Source: ko.nataviguides.com
Date Published: 3/7/2021
View: 8870
주제와 관련된 이미지 opencv hsv 색상 표
주제와 관련된 더 많은 사진을 참조하십시오 OpenCV Python 강좌 – 5. HSV 색공간에서 특정색 검출하기. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 opencv hsv 색상 표
- Author: 멈춤보단 천천히라도
- Views: 조회수 11,688회
- Likes: 좋아요 102개
- Date Published: 2018. 10. 16.
- Video Url link: https://www.youtube.com/watch?v=HGhj0Uef8K4
HSV 이미지를 사용하여 특정 색상 Object 추출하기
728×90
구현
1. RGB 이미지를 입력받아 HSV 이미지로 변환한다.
2. 색상의 범위에 따라 특정 색상의 객체를 추출하는 마스크를 생성한다.
3. 생성한 마스크에 따라 이미지를 계산하여 특정한 색상의 객체만 추출되는 결과 이미지를 만든다.
4. OpenCV를 사용해서도 해보고 안쓰고도 해봤다.
입력 이미지와 결과 이미지(orange 색상인 객체만 추출)
RGB to HSV
– 일단, 특정 색상 객체를 추출하기 위해서 왜 HSV 이미지가 필요한지부터 알아야 한다.
RGB 모델
출처 : https://tattly.com/products/rgb
– RGB 모델은 빛의 삼원색을 이용하여 색을 표현하는 기본적인 색상 모델
– 색을 빨강(Red), 초록(Green), 파랑(Blue), 3가지 성분의 조합으로 표현한다
– R, G, B값은 0~255 사이의 값들로 표현된다.
HSV 모델
출처 : https://ko.wikipedia.org/wiki/HSV_%EC%83%89_%EA%B3%B5%EA%B0%84#/media/File:HSV_cone.jpg
– HSV 모델은 인간의 색인지에 기반을 둔 색상 모델
– Hue(색조), Saturation(채도), Value(명도), 3가지 성분의 조합으로 표현
– Hue(색조) : 색의 종류. 0º~360º의 범위를 갖는다.
– Saturation(채도) : 색의 선명도, 진함의 정도(가장 진한 상태를 100%로 한다)
– Value(명도) : 색의 밝기, 밝은 정도(가장 밝은 상태를 100%로 한다)
RGB 에서 HSV로 변환하는 이유
– RGB 이미지에서 색 정보를 검출하기 위해서는 R, G, B 세가지 속성을 모두 참고해야한다.
– 하지만 HSV 이미지에서는 H(Hue)가 일정한 범위를 갖는 순수한 색 정보를 가지고 있기 때문에 RGB 이미지보다 쉽게 색을 분류할 수 있다.
RGB to HSV 공식
출처 : https://www.rapidtables.com/convert/color/rgb-to-hsv.html
– 위의 공식에서는 HSV 이미지를 H의 범위는 0~360으로 S, V는 0~1의 범위로 정규화 했다.
– OpenCV에서는 HSV 이미지를 H(0~180), S(0~255), V(0~255)로 표현한다.
– H(Hue)가 360이 아닌 180으로 범위를 지정한 이유는 OpenCV 이미지 변수들은 8bit로 설정되어 있어서 최대 255까지만 표현할 수 있기 때문이다.
mask 생성
– 모든 원소값이 0인 HSV 이미지와 같은 크기의 마스크 행렬을 만든다
– HSV 이미지 픽셀 값과 내가 원하는 색상 범위를 비교해서 픽셀 값이 색상 범위 안에 있을 경우, 그에 대응되는 위치의 마스크 행렬의 원소 값에 1을 입력한다.
– HSV의 색상 범위는 다음과 같다.
출처 : https://brunch.co.kr/@chulhochoiucj0/17
– 구현 과정에서 색상의 범위를 지정하는게 제일 힘들었다. 육안으로 내가 검출하는 색상의 H, S, V값을 정확히 알 수 없기 때문에, 어느정도 예상해서 범위를 지정한 다음 잘 검출되는 범위로 계속 수정했다.
– OpenCV에서 색조 범위는 0~180이므로 원하는 색상을 얻으려면 HSV 색상표 값에서 1/2 해줘야 한다.
※ 오렌지 색과 초록색은 색상표와 일치했는데 파란색은 전혀 다른 수치에서 검출되었다. 왜 그럴까…?🤔
mask를 이용한 object 추출 이미지 계산
– 원본 이미지에 대응되는 mask 행렬의 값에 따라 원본 이미지를 계산한다.
– mask 값이 1인 부분은 우리가 원하는 색상을 가지고 있기 때문에 R, G, B값을 그대로 가지고 있는다.
– mask 값이 0인 부분은 R, G, B값에 0을 곱해 검은 색으로 만든다.
Code
OpenCV를 사용해서 구현
import cv2 # matplotlib.image 를 사용하기 위해선 matplotlib 뿐만 아니라 pillow도 깔아야 한다. import matplotlib.pyplot as plt import matplotlib.image as mpimg # 색상 범위 설정 lower_orange = (100, 200, 200) upper_orange = (140, 255, 255) lower_green = (30, 80, 80) upper_green = (70, 255, 255) lower_blue = (0, 180, 55) upper_blue = (20, 255, 200) # 이미지 파일을 읽어온다 img = mpimg.imread(“test2.jpg”, cv2.IMREAD_COLOR) # BGR to HSV 변환 img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 색상 범위를 제한하여 mask 생성 img_mask = cv2.inRange(img_hsv, lower_orange, upper_orange) # 원본 이미지를 가지고 Object 추출 이미지로 생성 img_result = cv2.bitwise_and(img, img, mask=img_mask) # 결과 이미지 생성 imgplot = plt.imshow(img_result) plt.show()
OpenCV없이 구현
import numpy as np import matplotlib.pyplot as plt import matplotlib.image as mping def RGB2HSV(RGB): # HSV 색상을 얻기 위해서는 array 타입이 float이 되어야 계산할 수 있다 RGB_array = np.array(RGB).astype(np.float64) # 변환할 HSV 이미지 생성 HSV = np.array(RGB).astype(np.float64) # RGB 이미지의 width, height 저장 width, height = RGB_array.shape[:2] # 이미지 크기만큼 for 루프 for i in range(width): for j in range(height): # 공식 따라서 구현 var_R = RGB_array[i, j, 0] / 255.0 var_G = RGB_array[i, j, 1] / 255.0 var_B = RGB_array[i, j, 2] / 255.0 C_Min = min(var_R, var_G, var_B) C_Max = max(var_R, var_G, var_B) change = C_Max – C_Min V = C_Max if C_Max == 0: S = 0 else: S = change / C_Max if change == 0: H = 0 else: if var_R == C_Max: H = 60 * (((var_R – var_B)/change)%6) elif var_G == C_Max: H = 60 * (((var_B – var_R)/change)+2) elif var_B == C_Max: H = 60 * (((var_R – var_B)/change)+4) HSV[i, j, 0] = H HSV[i, j, 1] = S HSV[i, j, 2] = V return HSV def Mask(HSV, color): # 범위값과 비교할 hsv 이미지 생성, 파라미터에 있는 HSV를 그냥 쓰면 원소값이 float이 아닌 int로 나옴 hsv = np.array(HSV).astype(np.float64) # HSV 이미지의 width, height 저장 width, height = HSV.shape[:2] # 모든 값은 원소 값이 0 인 마스크 행렬 생성 mask = np.zeros((width, height)) # hsv 값과 범위 비교 for i in range(width): for j in range(height): # H, S, V 값이 원하는 범위 안에 들어갈 경우 mask 원소 값을 1로 만든다 if hsv[i, j, 0] > lower[color][0] and hsv[i, j, 1] > lower[color][1] and hsv[i, j, 2] > lower[color][2] and hsv[i, j, 0] < upper[color][0] and hsv[i, j, 1] < upper[color][1] and hsv[i, j, 2] < upper[color][2]: mask[i, j] = 1 return mask def Extraction(image, mask): # Object를 추출할 이미지를 생성 result_img = np.array(image) # RGB 이미지의 width, height 저장 width, height = image.shape[:2] # for 루프를 돌면서 mask 원소 값이 0인 인덱스는 원본 이미지도 0으로 만들어 준다. for i in range(width): for j in range(height): if(mask[i, j] == 0): result_img[i, j, 0] = 0 result_img[i, j, 1] = 0 result_img[i, j, 2] = 0 return result_img if __name__ == '__main__': # 마스크 색상 범위에 사용할 딕셔너리 정의 upper = {} lower = {} upper['orange'] = [100, 1, 1] upper['blue'] = [300, 1, 1] upper['green'] = [180, 0.7, 0.5] lower['orange'] = [0, 0.7, 0.5] lower['blue'] = [70, 0.7, 0.2] lower['green'] = [101, 0.15, 0] # 이미지 파일을 읽어온다 input_image = mping.imread('test2.jpg') # 추출하고 싶은 색상 입력 input_color = input("추출하고 싶은 색상을 입력하세요 (orange, blue, green) : ") # RGB to HSV 변환 HSV = RGB2HSV(input_image) # HSV 이미지를 가지고 마스크 생성 mask = Mask(HSV, input_color) # mask를 가지고 원본이미지를 Object 추출 이미지로 변환 result_image = Extraction(input_image, mask) #mping.imsave("result.jpg", result_image) # 이미지 보여주기 imgplot = plt.imshow(result_image) plt.show() 결과물 - 마지막 파란색 색상은 직접 구현했을때는 정확히 검출되지 않았다. - RGB to HSV 공식 구현에 문제가 있거나 아니면 색상 범위를 제대로 지정하지 못한 것 같은데 좀 더 수정이 필요하다. 참고사항 - OpenCV를 사용해서 읽어 들인 이미지를 matplotlib로 화면에 출력할 때, 출력한 색이 이상하게 나오는데 그 이유는 OpenCV에서는 컬러 이미지를 RGB가 아닌 BRG순서로 저장하는데 matplotlib에선 RGB 순서로 저장하기 때문이다. 따라서 matplotlib에서 출력할 때는 BRG를 RGB로 바꿔줘야 한다. - H, S, V값을 찾는게 생각보다 힘들었다. 일일이 찾는 무식한 방법이 아니라 원하는 픽셀 색상의 H, S, V 값을 확인할 수 있게 만들어야 범위를 쉽게 정할 수 있을 것 같다. 🤔 728x90
opencv 입문하기 7-2편 HSV, 특정 색상 추출(inRange)
1. HSV
HSV 색 공간 또는 HSV 모델은 색을 표현하는 하나의 방법이자, 그 방법에 따라 색을 배치하는 방식이다. 색상(Hue), 채도(Saturation), 명도(Value)의 좌표를 써서 특정한 색을 지정한다. 비슷한 것으로 HSL(Lightness), HSI(Intensity) 등이 있다.
RGB가 색을 빨강, 초록, 파랑의 조합으로 표현한다면, HSV는 우리가 보는 그대로의 색을 Hue 채널로 나타낸다. 그리고 그 색의 진하고 연한 정도를 Saturation 채널로 표현하고, 밝기를 Value로 결정한다.
RGB 색 공간보다는 좀 더 우리들이 색을 판단하는 과정과 유사한 것이 HSV 색 공간이다. 예를 들어 노란색을 표현하고자 하면, RGB 색 공간은 빨강과 초록의 조합으로 노랑을 표현해야하기에 직관성이 떨어진다. 반면 HSV 색 공간은 색들의 조합이 아닌 그 색깔 자체를 알려주므로 직관성이 좋다.
만약 색깔을 통해 이미지에서 어떤 물체를 검출하고 싶다면, RGB 공간보다는 HSV 공간이 적합할 것이다.
다음 그림은 HVS 색 공간을 한 눈에 설명해준다. 원뿔 모양으로 HSV 공간을 표현했는데, 우선 색조는 원뿔의 밑면에 해당되고 360도 연속적으로 배치되어 있음을 볼 수 있다. 그리고 명도는 원뿔의 높이에 해당한다. 꼭지점으로 갈수록 어두워진다.
채도는 원뿔의 밑면의 중심에서 가까울수록 연해지고 멀어질수록 진해진다.
색상 : H ) 0 – 360 의 범위를 가지고, 가장 파장이 긴 빨간색을 0도로 지정한다.
채도 : S ) 0 – 100 의 범위를 가지고, 색상이 가장 진한 상태를 100으로 하며, 진함의 정도를 나타낸다.
명도 : V ) 0 – 100 의 범위를 가지고, 흰색, 빨간색을 100, 검은색이 0이며, 밝은 정도를 나타낸다.
RGB -> HSV
import numpy as np import cv2 color = [255,0,0] # BGR 순서 ; 파란색 pixel = np.uint8([[color]]) # 한 픽셀로 구성된 이미지로 변환 # BGR -> HSV hsv = cv2.cvtColor(pixel, cv2.COLOR_BGR2HSV) print(hsv, ‘shape:’, hsv.shape ) # 픽셀값만 가져오기 hsv = hsv[0][0] print(“bgr: “, color) print(“hsv: “, hsv) # +_ 10
앞선 포스팅에서 RGB2HSV 를 종종 사용했었다.
위 코드를 실행해서 임의로 한 픽셀로 된 이미지를 만들어서 numpy array 를 살펴보자.
어떤 수식으로 변환할걸까? 공식문서에서 나온 공식을 참고 해보자.
H 는 0~360 , S 와 V 는 0~1 범위이다. 이는 맨 위에서 다룬 원뿔 모양으로 표현한 HSV 모델 구조를 생각해보면 이해가 될 것이다.
H는 절반값이고 나머지는 maximize 된 것으로 이해된다.
2. inRange(특정 색상 추출)
HSV 개념을 이해했다면 이를 활용하여 특정 생상을 추출해보겠습니다.
일반적으로 BGR 보다는 HSV 가 성능이 좋습니다.
결과
코드
# inRange import numpy as np import cv2 img_color = cv2.imread(‘color circle_w.jpg’) # 이미지 파일을 컬러로 불러옴 print(‘shape: ‘, img_color.shape) height, width = img_color.shape[:2] # 이미지의 높이와 너비 불러옴, 가로 [0], 세로[1] img_hsv = cv2.cvtColor(img_color, cv2.COLOR_BGR2HSV) # cvtColor 함수를 이용하여 hsv 색공간으로 변환 lower_blue = (120-10, 30, 30) # hsv 이미지에서 바이너리 이미지로 생성 , 적당한 값 30 upper_blue = (120+10, 255, 255) img_mask = cv2.inRange(img_hsv, lower_blue, upper_blue) # 범위내의 픽셀들은 흰색, 나머지 검은색 # 바이너리 이미지를 마스크로 사용하여 원본이미지에서 범위값에 해당하는 영상부분을 획득 img_result = cv2.bitwise_and(img_color, img_color, mask = img_mask) cv2.imshow(‘img_origin’, img_color) cv2.imshow(‘img_mask’, img_mask) cv2.imshow(‘img_color’, img_result) cv2.waitKey(0) cv2.destroyAllWindows()
중간에 color 이미지의 shape 은 shape: (472, 600, 3) 인데요.
여기서 472 는 행(Y축), 600 은 열(X축) , 3 은 행과열이 만나는 지점의 값이 몇개의 원소로 이루어져 있는지를 나타냅니다. 위 값의 의미는 이미지 사이즈는 600 * 472 (가로 * 세로) (너비 * 높이) 로 보시면 됩니다.
472 = 가로 = 너비
600 = 세로 = 높이
입니다.
위 결과를 조금 확대해서 보여드리자면,
### 2번째 이미지 ###
다른 이미지도 적용해보겠습니다.
위와 같은 이미지에서 특정 색상을 추출해보겠습니다.
# inRange 함수를 이용해서 특정 색상 검출 import cv2 src = cv2.imread(‘inRange.jpg’) # size 축소 src = cv2.resize(src, (0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_NEAREST) src_hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV) # 0 < B < 100 , 128 < G < 255 , 0 < R < 100 dst1 = cv2.inRange(src, (0, 128, 0), (100, 255, 100)) img_result = cv2.bitwise_and(src_hsv, src_hsv, mask = dst1) dst2 = cv2.inRange(src_hsv, (50, 150, 0), (80, 255, 255)) img_result2 = cv2.bitwise_and(src_hsv, src_hsv, mask = dst2) cv2.imshow('src', src) cv2.moveWindow('src',400,100) cv2.imshow('dst1', dst1) cv2.moveWindow('dst1',400,450) cv2.imshow('img_result', img_result) cv2.moveWindow('img_result',800,450) cv2.imshow('dst2', dst2) cv2.moveWindow('dst2',400,800) cv2.imshow('img_result2', img_result2) cv2.moveWindow('img_result2',1100,450) cv2.waitKey() cv2.destroyAllWindows() ** 참고 ** ttps://ko.wikipedia.org/wiki/HSV_%EC%83%89_%EA%B3%B5%EA%B0%84 https://bskyvision.com/46 https://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html https://velog.io/@nayeon_p00/OpenCV-Python-HSV-%EC%83%89%EA%B3%B5%EA%B0%84%EC%97%90%EC%84%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%9D%98-%ED%8A%B9%EC%A0%95%EC%83%89-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0 https://opencv-python.readthedocs.io/en/latest/doc/01.imageStart/imageStart.html
7. 이미지 색상 표현 방식(BGR, HSV, YUV)
이번 포스팅에서는 OpenCV로 색상을 표현하는 방식에 대해 알아보겠습니다. 이번 포스팅 역시 ‘파이썬으로 만드는 OpenCV 프로젝트(이세우 저)’를 정리한 것임을 밝힙니다.
코드: github.com/BaekKyunShin/OpenCV_Project_Python/tree/master/04.img_processing
BGR, BGRA
색상을 표현하는 방법으로는 RGB(Red, Green, Blue) 방식이 있습니다. 빨강, 초록, 파랑 세 가지 색의 빛을 섞어서 원하는 색을 만드는 방식입니다. 각 색상은 0~255 사이의 값으로 표시하고 값이 커질수록 해당 색상의 빛이 밝아지는 원리입니다. RGB = (255, 255, 255) 일 때는 흰색이고, RGB = (0, 0, 0) 일 때는 검은색입니다. 그러나 OpenCV는 그 반대의 순서인 BGR로 표현합니다. 예를 들어, 빨간색은 RGB 값으로 (255, 0, 0)이지만 BGR 값으로는 (0, 0, 255)입니다.
RGBA는 RGB에 A(알파, alpha)가 추가된 색상 표기법입니다. A는 배경의 투명도를 의미합니다. A 역시 0~255의 값을 가질 수 있지만, 배경의 투명도를 표현하기 위해 0과 255만 사용하는 경우가 많습니다. A값이 255면 흰색, 0이면 검은색입니다.
이제 아래의 예제 코드를 살펴보겠습니다. cv2.imread() 함수에 두 번째 파라미터로 cv2.IMREAD_COLOR를 넣어주면 BGR 방식으로 이미지를 읽습니다. cv2.IMREAD_UNCHANGED인 경우 이미지가 알파 채널을 가지고 있는 경우 BGRA 방식으로 읽습니다.
# BGR, BGRA, Ahlpha 채널 (rgba.py) import cv2 import numpy as np # 기본 값 옵션 img = cv2.imread(‘../img/opencv_logo.png’) # IMREAD_COLOR 옵션 bgr = cv2.imread(‘../img/opencv_logo.png’, cv2.IMREAD_COLOR) # IMREAD_UNCHANGED 옵션 bgra = cv2.imread(‘../img/opencv_logo.png’, cv2.IMREAD_UNCHANGED) # 각 옵션에 따른 이미지 shape print(“default”, img.shape, “color”, bgr.shape, “unchanged”, bgra.shape) cv2.imshow(‘bgr’, bgr) cv2.imshow(‘bgra’, bgra) cv2.imshow(‘alpha’, bgra[:,:,3]) # 알파 채널만 표시 cv2.waitKey(0) cv2.destroyAllWindows()
파라미터를 cv2.IMREAD_COLOR로 전달한 것과 아무 파라미터를 전달하지 않은 이미지의 차이는 없습니다. 배경이 검은색이다 보니 OpenCV라는 검은색 글씨도 안 보입니다. 또한, 첫 번째와 두 번째 이미지 모두 shape가 (240, 195, 3)입니다. 반면 세 번째 이미지는 알파 채널이 하나 더 있어 shape가 (240, 195, 4)입니다. 세 번째 이미지에서 전경의 알파 값은 255, 배경의 알파 값은 0인 것을 알 수 있습니다. 알파 값이 255면 흰색, 0이면 검은색이기 때문입니다. 첫 번째, 두 번째 이미지와 달리 세 번째 이미지는 알파 채널만 표시했으므로 전경과 배경을 쉽게 분리해서 볼 수 있습니다. 이런 이유로 알파 채널은 마스크 채널(mask channel)이라고도 부릅니다.
BGR 색상 이미지를 회색조 이미지로 변환하기
컬러 이미지를 회색조 이미지로 변환하는 것은 이미지 연산의 양을 줄여서 속도를 높이는 데 꼭 필요합니다. 처음부터 회색조로 읽어 들이는 함수는 cv2.imread(img, cv2.IMREAD_GRAYSCALE)입니다. cv2.imread() 함수의 두 번째 파라미터로 cv2.IMREAD_GRAYSCALE을 전달하면 됩니다. 그러나 처음에는 BGR 컬러 이미지로 읽어 들이고 그 이후에 회색조로 변환해야 할 때도 있습니다. 이는 cv2.cvtcolor() 함수로 구현할 수 있습니다. convert color의 약자입니다.
아래 코드는 색상 이미지를 회색조 이미지로 변환하는 두 가지 방법을 보여줍니다. 첫 번째 방법은 평균값을 이용해 직접 구현하는 것이고, 두 번째 방법은 OpenCV에서 제공하는 cv2.cvtcolor() 함수를 이용하는 것입니다.
# BGR 색상 이미지를 회색조 이미지로 변환 (bgr2gray.py) import cv2 import numpy as np img = cv2.imread(‘../img/yeosu.jpg’) img2 = img.astype(np.uint16) # dtype 변경 —① b,g,r = cv2.split(img2) # 채널 별로 분리 —② #b,g,r = img2[:,:,0], img2[:,:,1], img2[:,:,2] gray1 = ((b + g + r)/3).astype(np.uint8) # 평균 값 연산후 dtype 변경 —③ gray2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # BGR을 그레이 스케일로 변경 —④ cv2.imshow(‘original’, img) cv2.imshow(‘gray1’, gray1) cv2.imshow(‘gray2’, gray2) cv2.waitKey(0) cv2.destroyAllWindows()
gray1 이미지는 평균값을 이용해 회색조 이미지로 표현하는 알고리즘을 직접 구현한 것입니다. 평균을 구하기 전에 dtype을 unit16으로 바꿔주었습니다. 3 채널의 값을 합하면 255보다 큰 값이 나올 수 있기 때문입니다. 평균을 구한 뒤에는 다시 unit8로 바꿔줍니다.
cv2.split(img2) 함수는 BGR 채널별로 분리해서 튜플로 반환합니다. 이는 numpy 슬라이싱과 동일합니다. 따라서 아래의 두 코드는 동일한 코드입니다.
b, g, r = cv2.split(img2) b, g, r = img2[:, :, 0], img2[:, :, 1], img2[:, :, 2]
그러나 BGR 색상 이미지를 회색조 이미지로 바꾸기 위해서 단순히 평균값을 취하는 것 말고 함수를 이용하는 방법도 있습니다. 이는 cv2.cvtcolor(img, flag) 함수를 사용하면 되며, flag 파라미터에 cv2.COLOR_BRG2GRAY를 넣어주면 됩니다.
flag 파라미터는 총 274개이지만, 자주 사용되는 것은 아래와 같습니다.
cv2.COLOR_BGR2GRAY: BGR 색상 이미지를 회색조 이미지로 변환
cv2.COLOR_GRAY2BGR: 회색조 이미지를 BGR 색상 이미지로 변환
cv2.COLOR_BGR2RGB: BGR 색상 이미지를 RGB 색상 이미지로 변환
cv2.COLOR_BGR2HSV: BGR 색상 이미지를 HSV 색상 이미지로 변환
cv2.COLOR_HSV2BGR: HSV 색상 이미지를 BGR 색상 이미지로 변환
cv2.COLOR_BGR2YUV: BGR 색상 이미지를 YUV 색상 이미지로 변환
cv2.COLOR_YUV2BGR: YUB 색상 이미지를 BGR 색상 이미지로 변환
HSV, YUV에 대해서는 뒤이어 살펴보겠습니다. 참고로 cv2.COLOR_GRAY2BGR가 회색조 이미지를 BGR 색상 이미지로 변환하는 파라미터인데, 이는 실제 회색조 이미지를 색깔이 있는 이미지로 바꿔준다는 뜻이 아닙니다. 2차원의 배열을 갖는 이미지를 3개 채널 모두 같은 값을 갖는 3차원 배열로 변환한다는 뜻입니다. 이미지 간 연산을 할 때 차원이 다르면 연산이 불가능하므로 차원을 맞추기 위해 필요한 작업입니다.
HSV 방식
HSV 방식은 RGB와 마찬가지로 3개의 채널을 갖는 색상 이미지 표현법입니다. 3개의 채널은 H(Hue, 색조), S(Saturation, 채도), V(Value, 명도)입니다.
출처: 위키백과
위 그림에서 H, S, V를 보면 이해가 쉬울 것입니다. H 값은 이미지가 어떤 색상인지를 나타냅니다. S는 이미지의 색상이 얼마나 순수하게 포함되어 있는지를 나타냅니다. V는 색상이 얼마나 밝은지 어두운지를 표현합니다. cv2.cvtColor() 함수에서 두 번째 파라미터로 cv2.COLOR_BGR2HSV를 넣어주면 BGR 방식을 HSV 방식으로 변환합니다. cv2.COLOR_HSV2BGR을 넣어주면 HSV 방식을 BGR 방식으로 변환합니다. 아래는 BGR 방식을 HSV 방식으로 변환하는 예제 코드입니다.
# BGR을 HSV로 변환 (bgr2hsv.py) import cv2 import numpy as np #—① BGR 컬러 스페이스로 원색 픽셀 생성 red_bgr = np.array([[[0,0,255]]], dtype=np.uint8) # 빨강 값만 갖는 픽셀 green_bgr = np.array([[[0,255,0]]], dtype=np.uint8) # 초록 값만 갖는 픽셀 blue_bgr = np.array([[[255,0,0]]], dtype=np.uint8) # 파랑 값만 갖는 픽셀 yellow_bgr = np.array([[[0,255,255]]], dtype=np.uint8) # 노랑 값만 갖는 픽셀 #—② BGR 컬러 스페이스를 HSV 컬러 스페이스로 변환 red_hsv = cv2.cvtColor(red_bgr, cv2.COLOR_BGR2HSV); green_hsv = cv2.cvtColor(green_bgr, cv2.COLOR_BGR2HSV); blue_hsv = cv2.cvtColor(blue_bgr, cv2.COLOR_BGR2HSV); yellow_hsv = cv2.cvtColor(yellow_bgr, cv2.COLOR_BGR2HSV); #—③ HSV로 변환한 픽셀 출력 print(“red:”,red_hsv) print(“green:”, green_hsv) print(“blue”, blue_hsv) print(“yellow”, yellow_hsv)
BGR이 (0, 0, 255)인 색을 HSV로 표현하면 (0, 255, 255)입니다. 색상을 알아내기 위해서 RGB 방식은 세 가지 채널의 값을 모두 알아야 하지만, HSV 방식은 오직 H값 하나만 알면 되므로 좀 더 편리하고 효과적입니다.
YUV, YCbCr 방식
YUV 방식은 YCbCr 방식이라고도 하며, Y는 밝기(Luma), U는 밝기와 파란색과의 색상 차(Chroma Blue, Cb), V는 밝기와 빨간색과의 색상 차(Chroma Red, Cr)를 의미합니다. Y(밝기)에는 많은 비트수를 할당하고 U(Cb)와 V(Cr)에는 적은 비트수를 할당하여 데이터를 압축하는 효과를 갖습니다. 아래는 Y=0.5일 때, V와 U에 따른 YUV 방식의 색상 이미지 영역입니다.
출처: 위키백과, Y=0.5일 때
아래는 BGR 값을 YUV 값으로 변환하는 예제 코드입니다.
# BGR 값을 YUV로 변환 (bgr2yuv.py) import cv2 import numpy as np #—① BGR 컬러 스페이스로 3가지 밝기의 픽셀 생성 dark = np.array([[[0,0,0]]], dtype=np.uint8) # 3 채널 모두 0인 가장 어두운 픽셀 middle = np.array([[[127,127,127]]], dtype=np.uint8) # 3 채널 모두 127인 중간 밝기 픽셀 bright = np.array([[[255,255,255]]], dtype=np.uint8) # 3 채널 모두 255인 가장 밝은 픽셀 #—② BGR 컬러 스페이스를 YUV 컬러 스페이스로 변환 dark_yuv = cv2.cvtColor(dark, cv2.COLOR_BGR2YUV) middle_yuv = cv2.cvtColor(middle, cv2.COLOR_BGR2YUV) bright_yuv = cv2.cvtColor(bright, cv2.COLOR_BGR2YUV) #—③ YUV로 변환한 픽셀 출력 print(“dark:”,dark_yuv) print(“middle:”, middle_yuv) print(“bright”, bright_yuv)
BGR값은 (0, 0, 0), (127, 127, 127), (255, 255, 255)로 어두운 픽셀, 중간 밝기의 픽셀, 가장 밝은 픽셀입니다. 이를 YUV 방식으로 변환하면 각각 (0, 128, 128), (127, 128, 128), (255, 128, 128)입니다. 맨 처음 값인 Y가 밝기를 뜻한다고 했습니다. 두 번째, 세 번째 값은 동일한데 Y값만 0, 127, 255로 바뀝니다. 즉 어두운 값에서 밝은 값으로 변환하는 것을 볼 수 있습니다. 밝기에 좀 더 신경을 써야 한다면 BGR 방식보다 YUV 방식을 사용하는 것이 더 현명한 방법이겠죠?
요약하자면 OpenCV에서 색상을 표현하는 방식은 네 가지가 있습니다. BGR 방식, BGRA 방식, HSV 방식, YUV 방식입니다. BGR 방식은 전통적인 RGB 방식과 유사하며 그 순서만 반대입니다. BGRA 방식은 BGR 방식에서 투명도를 나타내는 A(알파) 값이 추가된 방식입니다. HSV 방식은 색조, 채도, 명도를 이용해서 색상을 표현하는 방식으로 H만 알면 색조는 어느 정도 파악이 가능합니다. 따라서 색조를 한눈에 알고자 한다면 HSV 방식을 사용하면 됩니다. YUV 방식은 밝기에 더 신경을 써야 하는 경우에 사용하면 좋습니다.
[C++ opencv] HSV 색상 검출하기
본문 목표
영상처리를 하다보면 특정 물체의 색을 인식해야할 상황이 주어진다.
컴퓨터에서 다룰 수 있는 색 영역은 크게 RGB 와 HSV 가 있는데,
RGB는 컴퓨터에 최적화 되어있고,
HSV는 사람의 눈과 비슷하다.
물체의 색을 인식한다면 사람과 같은 방식인 HSV 색 영역을 사용해야 하는데,
Opencv 에서 어떻게 HSV 색채널을 다룰 수 있는지 알아보자.
키워드 : inRange( ) , bitwise_and( ), HSV
알아볼 함수 원형
– 이중 임계값 처리 ( inRange )
Mat img = imread(“balls.jpg”); Mat img_hsv; cvtColor(img, img_hsv, COLOR_BGR2HSV); Mat yellow_mask, yellow_image; Scalar lower_yellow = Scalar(20, 20, 100); Scalar upper_yellow = Scalar(32, 255, 255); inRange(img_hsv, lower_yellow, upper_yellow, yellow_mask); bitwise_and(img, img, yellow_image, yellow_mask);
inRange( src , lower_value, upper_value, dst)
○ src : 입력할 이미지 변수
○ lower_value : threshold 값 1, 임계값 1 로 낮은 값을 입력,
○ upper_value : threshold 값 2, 임계값 2 로 높은 값을 입력
○ dst : 필터가 적용되어 저장될 이미지 변수
이 때, lower_value 와 upper_value 에는 Scalar 값으로 넣어 줘야 한다.
Scalar 값은 총 3가지 값으로, 색 채널에따라 순서가 달라진다.
RGB 의 경우에는 R G B 순서로 입력해야하고,
BGR 의 경우 B G R 순서로 입력해야 한다.
당연 HSV 의 경우에는 H S V 순서로 입력해야 한다.
inRange 함수는 이미 앞에서 다룬 적 있는 내용이므로, 관심있다면 참고하면 좋을 듯 하다.
https://diyver.tistory.com/69
HSV 가 뭔지 알아야 이번 내용이 이해가 된다.
HSV 색 채널은 사람의 색상 인식 방식과 같다고 앞에서 언급했다.
그러면 왜 HSV 색 채널을 사용하는지 알아야 이번 내용이 이해가 된다.
잠깐동안 왜 HSV 색 채널을 사용하는지 고민하는 시간을 가져보자.
사람은 어두운 곳에 있는 빨간색 공을 보고 빨간색이라고 인식한다.
그러나 RGB 색 채널을 사용하는 컴퓨터는 알기 어렵다.
어두운 곳에 있는 빨간색은 R G B 값 모두 부족하지만 그나마 R 값이 살짝 높다고 인식할 것이다.
매우 부정확한 방법이 될 수 있다.
그래서 컴퓨터에서 HSV 색 채널을 사용하는 것이다.
HSV 는 Hue 색상, Saturation 채도, Value 밝기(명도) 의 정보를 담은 색 채널이다.
위의 색 도형은 HSV 색 채널을 가시적으로 나타낸 것이다.
Hue 에 따라서 색상은 정해지게 되고,
Saturation 에 따라서 색상의 농도가 정해진다.
마지막으로 Value 에 따라서 색상의 밝기가 정해진다.
색상이 있다면 어두운데에 있던지, 밝은데에 있던지 Hue 값의 범위가 있으므로 감지가 가능한 것이다.
대신 어느정도 채도와 밝기를 띄고 있어야 인식이 가능하다.
포토샵 부터 다른 이미지 다루는 프로그램은 Hue 값을 0~360 범위로 사용한다.
그 이유는 위의 그림을 보면 알 수 있듯이, 원기둥이기 때문이다.
Hue 값에 따른 색상표를 제작해봤다. 대략적인 수치들을 기입해놓았으므로
필요한 수치는 위에서 참고하면 된다.
간혹 다르게 사용하는 경우가 있는데, 이는 데이터 값 때문이다.
보통 8bit 를 데이터 값으로 많이 사용하는데, 0~255 까지만 사용할 수 있어서 한계가 있다.
당장 ‘그림판’만 해도 HSV 색채널에는 0~240 까지만 사용한다.(RGB는 255 까지 사용)
OpenCV 에서는 Hue 값은 0~179 까지 사용할 수 있다. (180 은 0과 같다.)
Saturation 과 Value 값은 0~255 까지 사용할 수 있다.
따라서 원하는 색상 검출을 좀 정교하게 하고 싶은 경우,
그림판의 Hue 값을 참고하되 0.75 배를 해서 값을 사용해야 한다.
예를 들면, 노란색의 Hue 값이 그림판 상에서 39를 나타내고 있다면,
OpenCV에서는 0.75 배를 하고 반올림 한 29 를 사용해야한다.
이외에도 무료로 Hue 값을 알아볼 수 있는 무료 사이트들이 많으므로, 찾아서 이용하면 된다.
따라서 이러한 HSV 색 채널에 대한 특성을 이용하여,
OpenCV 의 기본 함수인 inRange 함수를 통해 해당 범위의 색을 골라낼 수 있다.
첫 번째의 threshold 값에는 낮은 값을 넣어야 한다.
두 번째의 threshold 값에는 높은 값을 넣어야 한다.
inRange( ) 함수는 threshold1 값 이상과 threshold2 값 이하의 범위만 밝은 값이 되고,
그 외의 범위는 검은색이 된다.
한마디로 이진화가 되는 것이다.
그런데 이미지에서 색상 추출한 부분을 컬러로 확인하고 싶은 경우에는
bitwise_and( ) 함수를 사용해야 한다.
bit 연산을 하는데, & 연산을 하는 것이다.
여기에는 위에서 다룬 inRange( ) 의 결과물이 mask로 사용된다.
검은색은 데이터로 나타내자면 0이 되고,
검은색 이외의 데이터는 True 값이므로,
검은색 부분은 & 연산으로 검은색이 되고,
검은색이 아닌부분은 원본의 색을 띄게 된다.
코드 테스트 결과
– CODE
#include
using namespace cv; using namespace std; int main(int ac, char** av) { Mat img = imread(“balls.jpg”); Mat img_hsv; cvtColor(img, img_hsv, COLOR_BGR2HSV); Mat yellow_mask, yellow_image; Scalar lower_yellow = Scalar(20, 20, 100); Scalar upper_yellow = Scalar(32, 255, 255); inRange(img_hsv, lower_yellow, upper_yellow, yellow_mask); bitwise_and(img, img, yellow_image, yellow_mask); imshow(“img”, img); imshow(“yellow_image”, yellow_image); imshow(“yellow_mask”, yellow_mask); waitKey(0); return 0; } – RESULT
사용한 원본이미지는 다양한 색상의 공들이 있는 사진이다.
balls.jpg 0.11MB
원본 파일은 BGR 채널이므로, HSV 채널로 변환시켜줘야 한다.
노란색을 검출할 것이므로,
yellow_mask 와 yellow_image 라는 이미지 변수를 만들어 준다.
그리고 inRange( ) 에서 사용할 값 두개를 미리 선언해준다.
lower_yellow 와 upper_yellow 라고 이름짓고, Hue 값은 20~32 범위로 설정하였다.
채도와 명도는 100~255 로 하면 적당하지만,
사용자의 입맛에 맞게끔 바꿔줘야 더 좋은 결과가 나온다.
inRange( ) 를 통해서 이진화된 이미지를 yellow_mask 에 저장하고,
bitwise_and( ) 함수를 이용하여, 원본이미지에 yellow_mask를 씌워서 bit 연산을 하고, yellow_image 에 저장한다.
inRange( ) 함수를 이용하여 노란색 범위만 이중 임계값으로 처리한 이진화 이미지이다.
노란색 부분만 하얗게 변한 것을 볼 수 있다.
그 외의 부분들은 검정색을 띄고있다.
bitwise_and( ) 함수의 결과 이미지이다.
bit 연산을 통해 원본 이미지에서 yellow_mask 와 연산한 것이다.
노란색만 살아남고, 결과에서도 노란색만 출력이 가능하다.
시각적인 결과가 필요하다면 bitwise_and( ) 함수를 사용해야 한다.
추가로 반사되어 노란 빛이 나는 부분이 있는데, 없애는 방법이 있다.
바로 이전에 배웠던 Opening 기법이다.
침식시키고 확장시키는 방법으로
erode 후에 dilate 를 적용하면 된다.
확실히 깔끔해 진 것을 볼 수 있다.
이처럼 erode 와 dilate 기법은 이런 자잘한 노이즈를 없앨 때, 유용하게 사용된다.
결론.
inRange( ) 함수를 이용하여 HSV 색채널을 이용한 색상 검출이 가능하다.
bitwise_and( ) 함수를 이용하여 색상 검출 된 영역을 컬러로 표현할 수 있다.
erode 와 dilate 를 이용하여 검출된 이미지에서 노이즈를 제거할 수 있다.
도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!
감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^
[OPENCV] 5. 색 공간 모델 HSV
반응형
☞ 메인보드 : Jetson Nano Developer Kit
☞ 운영 체제 : Ubuntu 18.04 – JetPack 4.4.1
☞ OpenCV 버전 : 4.2.0
☞ IDE : Visual Studio Code
☞ 언어 : C++
목차
○ 1. HSV란?
○ 2. OPENCV의 HSV함수
○ 3. 코드 작성
○ 4. 심화
구글에 HSV를 검색하면 신생아의 단순포진이나….함부르크 SV 축구팀이 나오지만 오늘은 색공간 모델인 HSV에 대해서 알아보도록 하겠다.
① HSV란?
출처: https://medium.com/neurosapiens/segmentation-and-classification-with-hsv-8f2406c62b39
지금은 TV의 화면을 보면 아주 부드럽다는? 느낌이 들어서 아무 생각이 안들지만 라떼는 브라운관 TV라 해서 화면에 가까이 다가가면 색이 변하는 아주 작은 점들을 볼 수 있었다. 이 점을 “몇 백만 화소” 할때의 화소라고 하는데 영어로 픽셀(Pixel)이라고 한다. 이 픽셀은 RED, GLEEN, BLUE 세 가지 색의 정도에 따라 혼합되어 다양한 색을 출력한다.
일반적으로는 픽셀의 index 원 투 쓰리를 담당하는 R, G, B 값은 색을 혼합할 수록 명도가 올라가는 가산혼합 방식으로 색을 표현한다. 많이 섞으면 흰색에 가깝고 덜 섞을수록 검정색에 가까운 모델인 것이다. 그에 비해 HSV 색 공간은 색을 혼합할 수록 밝아지는 가산혼합과 혼합할 수록 어두워지는 감산혼합과 같은 방식처럼 극단적이지 않기 때문에 말로 표현하기 쉽고 직관적이어 시각 예술에 자주 쓰인다고 한다.
HSV는 Hue(색상), Saturation(채도), Value(명도)의 앞 알파벳을 따서 이름이 지어졌는데 각 채널들은 아래와 같은 의미를 갖고 있다.
◎ Hue 색상 ☞ 색깔
◎ Saturation 채도 ☞ 색의 진하고 연한 정도
◎ Value 명도 ☞ 색의 밝고 어두운 정도
세 가지 채널에 대해 어떤 느낌인지 알려면 직접 코딩을 해서 눈알로 보는 수 밖에 없다. 일단은 HSV가 세 가지 채널에 의해 어떻게 출력되는지 결정된다는 것만 알고 넘어가면 된다.
② OPENCV의 HSV 함수
OPENCV의 함수를 볼 수 있는 사이트가 있다. 함수의 타입이나 매개변수 그리고 다양한 예제들까지 볼 수 있는 아주 유용한 사이트이다. 본인의 OPENCV 버전에 맞게 입장하자.
오른쪽에 보이는 검색창에 RGB2HSV나 cvtcolor 검색하면 OPENCV에서 사용하는 함수에 대해 알 수 있다.
바로 아래에 있는 cv::gapi::RGB2HSV(), cv::cvtColor()를 누르자.
RGB에서 HSV로 이미지를 전환시켜주는 함수라하고, 각 채널 값의 범위를 아두이노 PWM 출력처럼 0~255값으로 매핑해놓았다.
여기서 중요한 내용은 이미지 형식이 CV_8UC3 라는 것이다.
8UC3 ☞ 8bit의 Unsigned형 + 3개의 Channel
여기서 Unsigned는 부호가 없다는 것을 의미한다. 즉, 0값 아래의 음수(-)는 사용하지 않는다는 말이다.
3개의 Channel은 아까 설명한 Hue(색상), Saturation(채도), Value(명도) 세 가지를 의미한다.
[+ 0~255까지 256개의 값으로 매핑된 이유는 8bit 형식이기 때문이다. 8bit(1byte)는 0과 1로 이루어진 2진수를 이용하여 1bit짜리 메모리 박스 8칸을 채워넣을 수 있다. (00000000 ~ 11111111) 처럼 0과 1을 이용하여 2의 8제곱만큼의 경우의 수를 만들어낼 수 있기 때문에 0~255 값으로 사용되는 것이다. Hue는 (원기둥의 360도) 360가지의 색상을 다뤄야 했지만 256가지 밖에 다루지 못하여 최대값이 179이다.]cvtColor(InputArray src, OutputArray dst, code) 함수를 이용해서 HSV로 변환하는 과정은 조금 다르다.
함수의 첫 번째 매개변수 src에는 입력 이미지(RGB)를, 두 번째 매개변수 dst에는 출력 이미지(HSV) 변수들을 입력한다.
함수의 세 번째 매개변수 code 자리에 cv::COLOR_RGB2HSV를 입력해서 RGB 형식의 이미지를 HSV 이미지로 전환할 수 있다.
입력 이미지인 src 자리에는 부호가 없는 8비트[8UC], 16비트[16UC]의 이미지 형식을 넣을 수 있고 출력 이미지인 dst도 src와 같은 형식의 이미지를 반환하도록 되어있다. code 자리에는 다양한 전환 코드가 들어갈 수 있다. RGB2GRAY나 RGB2HSL 등 다양한 색 공간 모델을 전환할 수 있다.
위에서 언급한 이미지 형식과 다른 이미지 형식으로 해당 함수에 대입하게되면 곧 에러를 반환한다. 다양한 이미지 형식으로 작업을 하고 싶다면 각각 객체를 만들어 지정하는 작업을 한 후에 하도록 하는 것이 바람직하다.
이렇게만 봐서는 느낌이 안오니 직접 해보도록 하자.
③ 코드 작성
프로젝트를 생성하고 VS Code를 실행한다. 다운로드를 안했으면 아래 링크에서 설치 방법이 있으니 참고 바란다.
mkdir ~/workspace/colorModel/src code
그리고 예제에 사용할 요 이미지를 받아서 ~/workspace/colorModel 디렉터리 안에 넣어준다.
※ hsv.cpp
파일 위치 ☞ ~/workspace/colorModel/src/hsv.cpp
#include
#include #include int main(){ int width = 600, height = 400; cv::Mat img, hsv; img = cv::imread(“road2.jpg”, cv::IMREAD_COLOR); cv::cvtColor(img, hsv, cv::COLOR_RGB2HSV); if(img.empty()){ std::cout << "No Image" << std::endl; return -1; } cv::namedWindow("ORIGINAL IMAGE", cv::WINDOW_NORMAL); cv::resizeWindow("ORIGINAL IMAGE", width, height); cv::imshow("ORIGINAL IMAGE", img); cv::namedWindow("HSV IMAGE", cv::WINDOW_NORMAL); cv::resizeWindow("HSV IMAGE", width, height); cv::imshow("HSV IMAGE", hsv); cv::waitKey(0); } ※ CMakeLists.txt 파일 위치 ☞ ~/workspace/colorModel/src/hsv.cpp cmake_minimum_required(VERSION 2.9) project(colorModel) find_package(OpenCV REQUIRED) add_executable(${PROJECT_NAME} src/hsv.cpp) target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) cmake . 파일 작성을 완료했으면 cmake해서 makefile을 생성한다. cmake를 완료했으면 make를 해서 오브젝트(실행) 파일을 만들어준다. make ./colorModel 왼쪽이 원본, 오른쪽이 HSV 이미지다. 환술에 걸린 이미지 같이 생겼다. ④ 심화 ※ ROI(Region Of Interest) #include #include #include int main(){ cv::Mat img, ROI; img = cv::imread(“road2.jpg”, cv::IMREAD_COLOR); cv::resize(img, img, cv::Size(600,480)); if(img.empty()){ std::cout << "No Image" << std::endl; return -1; } ROI = img(cv::Rect(0,250,600,230)); cv::namedWindow("ORIGINAL IMAGE", cv::WINDOW_NORMAL); cv::resizeWindow("ORIGINAL IMAGE",600, 480); cv::imshow("ORIGINAL IMAGE", ROI); cv::waitKey(0); } 양쪽에 있는 흰색 차선을 인식해보려고 한다. 그럼 인식하기 위해서 첫째로 할 수 있는 일은 차선 이외에 나머지 부분을 지워버리는 일이다 이를 "ROI(관심영역)을 지정한다." 라고 한다. cv::Rect를 이용하면 이미지 화면의 크기를 편집할 수 있다. int main(){ cv::Mat img, ROI; img = cv::imread("road2.jpg", cv::IMREAD_COLOR); cv::resize(img, img, cv::Size(600,480)); Mat 형식의 img, ROI 객체를 만들고 img에 cv::imread로 불러온 이미지를 저장한다. 이미지 사이즈가 너무 커서 cv::resize를 이용하여 이미지 너비와 높이를 600, 480 값으로 재지정했다. if(img.empty()){ std::cout << "No Image" << std::endl; return -1; } cv::imread로 이미지를 불러오지 못한 경우에는 오류를 출력할 수 있도록 하였다. ROI = img(cv::Rect(0,250,600,230)); cv::namedWindow("ORIGINAL IMAGE", cv::WINDOW_NORMAL); cv::resizeWindow("ORIGINAL IMAGE",600, 480); cv::imshow("ORIGINAL IMAGE", ROI); cv::waitKey(0); } cv::Rect(시작 점X 값, 시작 점Y 값, 너비 값, 높이 값) opencv docs에서 cv::Rect를 읽었는데 머리가 안좋아서 이해를 못하다보니 그림으로 그려가면서 하게되었다. 매개변수 4곳에 무엇이 들어가는지 몰라서 계속 에러가 생겼다. 무튼 위와 같은 코드를 작성하면 아래와 같은 화면 원본 이미지의 일정 부분이 잘린 화면이 나온다. ※ 수정한 코드 #include #include #include int main(){ cv::Mat img, HSV, ROI; img = cv::imread(“road2.jpg”, cv::IMREAD_COLOR); cv::resize(img, img, cv::Size(600,480)); if(img.empty()){ std::cout << "No Image" << std::endl; return -1; } ROI = img(cv::Rect(0,250,600,230)); cvtColor(ROI,HSV,cv::COLOR_RGB2HSV); cv::Scalar lower_white = cv::Scalar(0,0,200); cv::Scalar upper_white = cv::Scalar(180,255,255); cv::inRange(HSV, lower_white, upper_white, HSV); cv::imshow("ORIGINAL IMAGE", ROI); cv::imshow("HSV IMAGE", HSV); cv::waitKey(0); } ROI 관심영역으로만 픽셀을 줄여놓은 후 그 부분을 HSV 색 공간 모델로 전환하였다. 차선이 흰색이므로 HSV에서의 흰색의 범위를 lower_white, upper_white로 지정해주었고 이를 cv::inRange()로 지정된 범위 만큼의 색만 출력하게끔 했다. 만약 중간에 있는 차선이 거슬린다면 허프라인으로 흰색 선을 따고 해당 라인의 X,Y 값을 이용하여 아크탄젠트 값을 구하고 기울기가 90도에 가깝다면 흰색 선으로 인식하지 않는 방법을 사용해도 된다. 이는 필터 효과, 이미지 프로세싱을 함께 다루며 진행하도록 하겠다. 반응형
Opencv 파이썬 Colab – Hsv로 변환 및 원하는 색상 부분 추출하기 | opencv hsv 색상 표 오늘 업데이트
We are using cookies to give you the best experience on our website.
You can find out more about which cookies we are using or switch them off in settings.
OpenCV를 이용하여 특정색 (빨간색) 검출
반응형
아래 유튜브 영상에 본 포스팅을 개선한 내용이 포함되어 있습니다.
최종업데이트 – 2018. 6. 10
OpenCV를 이용하여 카메라로부터 캡쳐되는 영상은 BGR 영상입니다.
RGB가 아니라 BGR이라고 부르는 것은 Blue, Green, Red 순으로 한 픽셀이 구성되기 때문입니다.
코드에서는 HSV 영상으로 변환한 후, 영상에서 원하는 색을 분리하고 있습니다.
HSV 영상에서 Hue 성분은 다음처럼 특정 색의 컬러가 일정한 범위를 갖기 때문에 분리해내기가 쉽습니다.
이미지 출처 : https://www.dreamstime.com/stock-illustration-color-colors-wheel-names-degrees-rgb-hsb-hsv-hue-image78027630
참고 [2]에 따르면 cvtColor 함수를 사용하여 변화하면 0 < Hue < 179, 0 < Saturation < 255, 0 < Value < 255 의 범위를 갖습니다. 위 그림의 값에 0.5를 곱하면 원하는 색의 hue 값입니다. 예제 코드에서는 Scalar 객체로 원하는 색의 값을 B, G , R 순으로 선언한 후, Hue 값의 범위에 맞추어 마스크 영상을 만들어줍니다. 현재는 빨간색, 파란색, 노란색, 자홍색만 코드에 포함되어 있습니다. 아래 영상은 노란색을 검출해본 결과입니다. 검출된 노란 물체 주변으로 빨간색 사각형이 보입니다. 단순히 구현하기 위해서 형태를 보지 않고 가장 큰 물체를 기준으로 사각형이 그려집니다. 테스트에 사용된 영상입니다. 실제 카메라로 할 경우에는 조명이 너무 어둡거나 너무 밝으면 안좋은 결과가 보일 수 도 있습니다. test.mp4 #include
#include
using namespace cv;
using namespace std;
int main()
{
int range_count = 0;
Scalar red(0, 0, 255);
Scalar blue(255, 0, 0);
Scalar yellow(0, 255, 255); Scalar magenta(255, 0, 255);
Mat rgb_color = Mat(1, 1, CV_8UC3, red);
Mat hsv_color;
cvtColor(rgb_color, hsv_color, COLOR_BGR2HSV);
int hue = (int)hsv_color.at
(0, 0)[0]; int saturation = (int)hsv_color.at
(0, 0)[1]; int value = (int)hsv_color.at
(0, 0)[2]; cout << "hue = " << hue << endl; cout << "saturation = " << saturation << endl; cout << "value = " << value << endl; int low_hue = hue - 10; int high_hue = hue + 10; int low_hue1 = 0, low_hue2 = 0; int high_hue1 = 0, high_hue2 = 0; if (low_hue < 10 ) { range_count = 2; high_hue1 = 180; low_hue1 = low_hue + 180; high_hue2 = high_hue; low_hue2 = 0; } else if (high_hue > 170) {
range_count = 2;
high_hue1 = low_hue;
low_hue1 = 180;
high_hue2 = high_hue – 180;
low_hue2 = 0;
}
else {
range_count = 1;
low_hue1 = low_hue;
high_hue1 = high_hue;
}
cout << low_hue1 << " " << high_hue1 << endl; cout << low_hue2 << " " << high_hue2 << endl; VideoCapture cap("test.mp4"); Mat img_frame, img_hsv; if (!cap.isOpened()) { cerr << "ERROR! Unable to open camera "; return -1; } for (;;) { // wait for a new frame from camera and store it into 'frame' cap.read(img_frame); // check if we succeeded if (img_frame.empty()) { cerr << "ERROR! blank frame grabbed "; break; } //HSV로 변환 cvtColor(img_frame, img_hsv, COLOR_BGR2HSV); //지정한 HSV 범위를 이용하여 영상을 이진화 Mat img_mask1, img_mask2; inRange(img_hsv, Scalar(low_hue1, 50, 50), Scalar(high_hue1, 255, 255), img_mask1); if (range_count == 2) { inRange(img_hsv, Scalar(low_hue2, 50, 50), Scalar(high_hue2, 255, 255), img_mask2); img_mask1 |= img_mask2; } //morphological opening 작은 점들을 제거 erode(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); dilate(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); //morphological closing 영역의 구멍 메우기 dilate(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); erode(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); //라벨링 Mat img_labels, stats, centroids; int numOfLables = connectedComponentsWithStats(img_mask1, img_labels, stats, centroids, 8, CV_32S); //영역박스 그리기 int max = -1, idx = 0; for (int j = 1; j < numOfLables; j++) { int area = stats.at
(j, CC_STAT_AREA); if (max < area) { max = area; idx = j; } } int left = stats.at
(idx, CC_STAT_LEFT); int top = stats.at
(idx, CC_STAT_TOP); int width = stats.at
(idx, CC_STAT_WIDTH); int height = stats.at
(idx, CC_STAT_HEIGHT); rectangle(img_frame, Point(left, top), Point(left + width, top + height),
Scalar(0, 0, 255), 1);
imshow(“이진화 영상”, img_mask1);
imshow(“원본 영상”, img_frame);
if (waitKey(5) >= 0)
break;
}
return 0;
}
참고
[1] https://stackoverflow.com/questions/32522989/opencv-better-detection-of-red-color [2] https://docs.opencv.org/3.4.1/df/d9d/tutorial_py_colorspaces.html [3] https://github.com/opencv/opencv/blob/master/samples/cpp/videocapture_basic.cpp반응형
HSV (색상, 채도, 명도)
HSV (색상, 채도, 명도)
색을 RGB로 많이 표현하지만 색을 HSV (색상, 채도, 명도)는 나타낼 수도 있다.
H (Hue) 색상: 빨강, 파랑, 노랑 등과 같은 색의 종류를 나타낸다.
S (Saturation) 채도: 짙은 빨강, 옅은 빨강 등의 색의 진한 정도
V (Value) 명도: 밝은 빨강, 어두운 빨강 등과 같은 색의 밝기
아래 그림과 같이 색상(H)가 변할 때는 색의 종류가 바뀌고 채도(S)가 변할 때는 색의 진한 정도가 바뀌고 명도(V)가 변할 때는 색의 밝기가 바뀐다.
RGB를 HSV로 변환하는 공식
OpenCV에서 RGB를 HSV로 변환하는 공식은 다음과 같다.
여기서, R,G,B는 0~1의 범위로 가진다. RGB가 0~255의 범위일 때는 255로 나누어준다.
V와 S는 0~1의 범위를 가지고 H는 0~360의 범위를 가진다. H가 0보다 작으면 360을 더하여 최종 H를 구한다.
H (Hue)
색상 빨강, 파랑과 같은 색의 종류
0 = 빨강(Red), 120=초록(Green), 240=파랑(Blue) S (Saturation)
채도 짙은 빨강, 옅은 빨강과 같은 진한 상태 V (Value)
명도 밝은 빨강, 어두운 빨강과 같은 밝기
윈도우의 그림판에서 HSV를 확인할 수 있다.
기타
☞ OpenCV RGB HSV 변환
☞ RGB HSV 변환 소스 코드
반응형
키워드에 대한 정보 opencv hsv 색상 표
다음은 Bing에서 opencv hsv 색상 표 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 OpenCV Python 강좌 – 5. HSV 색공간에서 특정색 검출하기
- OpenCV
- Python
- OpenCV 강좌
- HSV
- BGR
- RGB
- 특정색
- 색검출
- color detection
OpenCV #Python #강좌 # #- #5. #HSV #색공간에서 #특정색 #검출하기
YouTube에서 opencv hsv 색상 표 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 OpenCV Python 강좌 – 5. HSV 색공간에서 특정색 검출하기 | opencv hsv 색상 표, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.