HSV는 H(Hue; 색조), S(Saturation; 채도), V(Value; 명도)로 이미지를 표현하는 것으로 RGB와 같은 하나의 색 공간이다. RGB가 색을 빨강, 초록, 파랑의 조합으로 표현한다면, HSV는 우리가 보는 그대로의 색을 Hue 채널로 나타낸다. 그리고 그 색의 진하고 연한 정도를 Saturation 채널로 표현하고, 밝기를 Value로 결정한다. RGB 색 공간보다는 좀 더 우리들이 색을 판단하는 과정과 유사한 것이 HSV 색 공간이다. 왜냐하면 예를 들어 노란색을 표현하고자 하면, RGB 색 공간은 빨강과 초록의 조합으로 노랑을 표현해야하기에 직관성이 떨어진다. 반면 HSV 색 공간은 색들의 조합이 아닌 그 색깔 자체를 알려주므로 직관성이 좋다. 만약 색깔을 통해 이미지에서 어떤 물체를 검출하고 싶다면, RGB 공간보다는 HSV 공간이 적합할 것이다(아래 예제를 통해 가능성을 확인하자). 그림1은 HVS 색 공간을 한 눈에 설명해준다. 원뿔 모양으로 HSV 공간을 표현했는데, 우선 색조는 원뿔의 밑면에 해당되고 360도 연속적으로 배치되어 있음을 볼 수 있다. 그리고 명도는 원뿔의 높이에 해당한다. 꼭지점으로 갈수록 어두워진다. 채도는 원뿔의 밑면의 중심에서 가까울수록 연해지고 멀어질수록 진해진다. 


그림 1. HSV 색 공간


색깔을 통해 어떤 물체를 검출하고자 하면 우선 Hue 채널의 값들이 무슨 색깔과 매칭되는지를 알아야한다. 매트랩에서는 Hue 채널은 0~1사이의 값들을 갖는데, 아래 그림2와 같이 매칭되어 있다. 동그랗게 말려 있는 것을 펼치면 이렇게 될 것이다. 


그림 2. HSV 컬러 범위


그림3을 보면 HSV 색 공간에 대해 좀 더 명확하게 이해가 될 것이다. 우선 H값은 하나의 값으로 고정시킨 다음, S와 V의 값을 선형적으로 변화시켜봤다. H = 0일때는 빨간색이고, S와 V가 커질수록 좀 더 진하고 밝은 빨간색이 됨을 확인할 수 있다. H = 0.25, 0.5, 0.75, 1에서도 마찬가지로 S와 V가 커질수록 좀 더 진해지면서 좀 더 밝아진다. 그리고 또 주목할 것은 H = 0과 H = 1이 같은 색을 의미한다는 것이다. 그림1에서와 같이 360도 돌았기 때문에 결국 같은 색으로 돌아온 것이다.  


그림 3. 고정된 H 값에서 S와 V 값을 변화시킨 이미지들.

 

어느 정도 HSV 색 공간에서 H, S, V 채널이 각각 무엇을 의미하는지 이해했다면, RGB 이미지를 HSV 채널로 변환한 다음에 각 채널의 내용물을 확인해보자(그림4). 


그림4. HSV 이미지와 각 채널들.


H채널은 색상 자체를 나타내고, S채널은 그 색의 진함을 나타내고, V채널은 밝기만을 나타내고 있다. H채널만 좀 더 자세하게 살펴보자(그림5).


 

Hue 채널에서 빨간색 계열은 0과 1부근에 매칭되어 있다(무슨 말인지 이해가 안된다면 그림2를 참고하자). H 채널에서 볼 수 있듯이 붉은 화초는 1에 가까운 값을 가지므로 거의 가장 밝게 표현되었다. 그리고 오른쪽 상단의 그림에는 푸른 색깔을 가지므로 약 0.5인 중간 밝기정도의 회색으로 표현되었다. 이런 방식으로 모든 색상이 0과 1사이의 값으로 표현되어 있다. 


그럼 간단한 예제를 구현해보자. 초록색, 빨간색 사과들이 있다(그림6). 

그림6. 사과 이미지


여기서 빨간색 사과만 검출해보자. HSV 색 공간으로 전환하자(그림6-1). 


그림6-1. HSV 색 공간


S채널과 V채널을 봐서는 빨간 사과와 초록 사과를 분간해낼 수 없지만, H채널을 보면 분명히 다른 값들을 갖고 있음을 알 수 있다. 이를 통해 0 <= h < 0.1과 0.95< h <= 1이면 빨간 사과를 나타내는 색조 범위라고 판단했다. 그런데 흰 배경도 빨간 사과와 거의 비슷한 값을 갖고 있다. 그래서 S채널에서 채도를 확인해서 채도가 너무 작으면(색이 너무 옅으면) 배경일 것이라 판단했고, V채널에서 명암을 확인해서 명암이 너무 크면(너무 밝으면) 배경일 것이라 판단했다. 따라서 s > 0.4, v < 0.97로 세팅했다. 이를 구현하는 소스 코드는 아래와 같다.


clear, clc, close all


img_rgb = imread('apples.jpg');


figure, imshow(img_rgb)


img_hsv = rgb2hsv(img_rgb); // RGB 이미지를 HSV 이미지로 전환


img_hsv_h = img_hsv(:,:,1); // Hue 채널

img_hsv_s = img_hsv(:,:,2); // Saturation 채널

img_hsv_v = img_hsv(:,:,3); // Value 채널


img_hsv_red = double(zeros(size(img_hsv_h))); 


for i = 1: size(img_hsv_red, 1)

    for j = 1:size(img_hsv_red, 2)

        if (img_hsv_h(i, j) > 0.95 || img_hsv_h(i, j) < 0.1) && (img_hsv_v(i, j) < 0.97) && (img_hsv_s(i,j) > 0.4) // 여기가 핵심!! 

            img_hsv_red(i, j) = 1;

        end

    end

end


img_rgb_red = uint8(zeros([size(img_hsv_red), 3]));

for i = 1:size(img_hsv_red, 1)

    for j = 1:size(img_hsv_red, 2)

        if img_hsv_red(i, j) ~= 0

            img_rgb_red(i, j, :) = img_rgb(i, j, :);

        end

    end

end


figure, imshow(img_rgb_red)


이제 결과물을 살펴보자 (그림6). 거의 정확하게 빨간 사과만 검출한 것을 확인할 수 있다. 예전에 RGB채널에서 G 채널의 영상 이진화를 이용해서 빨간 사과를 찾았던 것보다 훨씬 더 나은 결과를 산출하는 것을 확인할 수 있다. 

(http://blueskyvision.tistory.com/23)


그림6. 검출된 빨간 사과 이미지


이처럼 HSV 색 공간을 잘 활용한다면, 필요한 색상의 물체를 찾아낼 수 있다. 특정 물체를 검출하는 훨씬 더 발전된 방법들이 많이 있지만, 이런 기초적인 것들을 알고 있는 것도 큰 도움이 된다. 

  1. 2017.11.07 18:08

    비밀댓글입니다

    • 2017.11.07 19:22

      비밀댓글입니다

  2. 2017.11.08 16:24

    비밀댓글입니다

    • 2017.11.08 16:47

      비밀댓글입니다

    • 2017.11.08 17:22

      비밀댓글입니다

  3. 2018.11.17 02:45

    비밀댓글입니다

    • 2018.11.17 10:02

      비밀댓글입니다

    • BlogIcon kkkk0000 2018.11.17 23:26 신고

      제가 이 댓글을 썻는데 비회원으로 써서 답글이 안보이는데..다시 답글 달아주시면 안될가요...

    • BlogIcon 톈진난만 2018.11.18 10:39 신고

      숫자들을 잘 설정하면 가능은 할것같아요 ㅎㅎ 얼굴을 인식하고 싶으신건가요? 아니면 피부색만을 검출하고 싶으신건가요??

  4. 2018.11.18 15:47

    비밀댓글입니다

    • BlogIcon 톈진난만 2018.11.18 16:29 신고

      아 그렇다면 단순히 색을 이용해서만은 검출하기 쉽지 않을 것 같은데요^^; 다른 특성을 고려해야할것 같아요 ㅎㅎ

+ Recent posts

티스토리 툴바