이전 장에서 학습한 HSV포맷을 기준으로 2D Histogram 분석을 진행하겠다 

 

1. 2D Histogram 

  • calcHist()  : 1D와 마찬가지로 calcHist 함수를 이용하여 HSV 포맷의 Hue와 Saturation의 histogram을 생성하겠다
from typing import no_type_check
import cv2
import numpy as np
from matplotlib import pyplot as plt

image = cv2.imread('test.jpg')
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
hist = cv2.calcHist(hsv_image,[0,1], None, [360,256], [0,360,0,256])
stack_hist = np.stack((hist,)*3,axis=-1)
print('image의 shape \t\t: ',image.shape)
print('hist의 shape \t\t: ',hist.shape)
print('stack hist의 shape \t: ',stack_hist.shape)

fig = plt.figure(figsize=(8,3))
plt.tight_layout()
plt.subplot((131)),plt.imshow(image)
plt.subplot((132)),plt.imshow(hist)
plt.subplot((133)),plt.imshow(stack_hist)

plt.show()

  • 기존 1D Histogram을 그릴 때와 변경된 부분은
    4번째 파라미터인 x축 간격이 2개의 값을 넘겨 x와 y축으로 변경되었고
    5번째 파라미터인 축의 범위또한 x, y 각각 0~360 , 0~256의 범위로 설정되었다 
  • 1D 일 때는 ply.plot으로 그래프를 그렸지만 2D에서는 imshow를 통해 보였다 그 이유는 1D에서는 각 그 값에 해당하는 픽셀의 개수를 표현했지만 2D에서는 H일 때 S 픽셀이 있나 를 표현해서 0, 1 의값이 리턴된다 그렇기 때문에 plot으로 2D를 그리면 0과 1만 표현된다 
  • hist의 결과값은 H, S 2개의 값이 리턴되기 때문에 shape이 (360,256)이 된다 위에 가운데 사진에 보다시피 imshow로 보였을 때 잘 구분이 되지 않는다 
  • 좀더 보기 쉽게 np.stack을 통해 RGB 같은 (360,256,3)의 shape으로 변경하였다
  • 여기서 의문이 생긴다 각 값이 0과 1로 표현됐는데 왜 결괏값으로 보이는 이미지는 왜 검은색과 하얀색으로 표현되나 하얀색은 255가 아닌가? matplotlib.pyplot에서 0과 1로 되어있는 데이터는 자동으로 0,255로 변경해준다 

  • 자 이제 나온 결과값을 해석해 보자 
  • 세로의 값은 Hue를 뜻한다 (100,110) 정도에 점이 찍혀있다 그 뜻은 Hue:110, Saturation:100이란 뜻이므로 약간 어두운 초록색 부분이 많다는 뜻이다 사진에서 숲의 영역을 뜻한다
  • 또한 H:160~250 S:150~200 까지의 부분에 점이 몰려있다 그 뜻은 밝은 하늘색이 다양한 밝기와 색상으로 존재한다는 뜻이다 사진에서 바다와 하늘을 뜻한다

 

다음장에서는 바운딩 박스를 읽어와

해당 바운딩박스 내에 객체들이

어떤 특성을 가지고 있는지 분석해 보겠다

이전 글에서는 히스토그램을 이용한 1D 분석에 대하여 작성하였다 

1D 히스토그램을 이용하면 Gray scale로 이미지의 밝기 분포를 볼 수 있고 

Color scale을 통해 R,G,B 값의 분포를 확인할 수 있다. 

 

이번 글에서는 2D Histogram을 이용한 채도( saturation ), 색상(Hue) 에 대하여 분석하기 앞서
HSV - Hue, Saturation, Value 포멧에 대하여 설명하겠다 

1. HSV Color space 

  • Hue - 색상 : 일반적인 색깔을 의미한다 . HSV 포멧에서는 각도로 표현된다 0º 부터 120º 마다 각각 Red Green Blue를 뜻한다 
  • Saturation - 채도 : 색의 순수성을 의미한다. 색이 짙다 흐리다로 표현된다 HSV 포멧에서 중심에서 바깥쪽으로 이동하면 채도가 높다 
  • Value - 명도 : 밝기를 의미한다. HSV 포멧에서 수직측의 깊이로 표현된다 값이 작을 수록 어둡다  
import cv2
import numpy as np
from matplotlib import pyplot as plt

origin_image = cv2.imread('puppy.jpg')
hsv_image = cv2.cvtColor(origin_image, cv2.COLOR_BGR2HSV)
image = np.concatenate((origin_image,hsv_image), axis=1)

print('원본 : \t',origin_image[0,0,:])
print('hsv : \t',hsv_image[0,0,:])

cv2.imshow('HSV', image)
cv2.waitKey(0)

BGR과 HSV 포멧의 imshow

  • BGR 포멧과 HSV 포멧을 imshow를 통해 보여봤다 hsv 포멧에서 이미지의 색상이 이상하게 변하는것은 현재 imread가 hsv 포멧을 생각안하고 BGR 포멧이라고 인식하여 읽어왔기 때문이다 

  • 각 원본 이미지와 hsv 포멧의 가장 왼쪽 위의 값을 찍어보면 다음과 같다 각각  B,G,R를 뜻하던 값이 H,S,V를 뜻하는 값으로 변경되었다
  • 원본에서 눈으로 봤을 때 하얀색과 가깝다 그렇기 때문에 BGR값이 모두 높은 220대가 나왔다 
  • HSV의 값은 120의 H 값은 위의 HSV 색상 공간 그림을 봤을 떄는 초록색의 방향이다 하지만 S의 값이 11이라는 낮은 값이 나와 채도는 의미가 낮아졌고 다음 V의 값이 232로 높은 값이 나와 밝은 값이라고 알 수 있다.
  • 강아지의 눈동자 부분의 값을 찍어보았다 BGR의 값이 전체적으로 낮아져 어두운 색상을 의미한다 
  • HSV의 경우 밝기를 뜻하는 V의 값이 낮아져 어두운 부분이라고 알 수 있다.

 

2. 이미지 값 조절 

  • 이미지에서 각 포멧의 값을 늘리거나 줄이는 방법을 이용하여 이미지의 특정 부분을 수정할 수 있다 
  • cv2.add(image, value_array), cv2.subtract(image, value_array)
  • 각 함수의 첫번쨰 파라미터는 변경할 이미지
  • 두번째 파라미터는 더하거나 빼거나 할 값이다
  • cv2.add, cv2.subtract에서는 0이하의 값들은 모두 0으로 취급하고 255이상의 값은 모두 255로 취급한다
import cv2
import numpy as np
from matplotlib import pyplot as plt

origin_image = cv2.imread('puppy.jpg')
hsv_image = cv2.cvtColor(origin_image, cv2.COLOR_BGR2HSV)

val = 100
array = np.full(hsv_image.shape, (0,0,val), dtype=np.uint8)

val_add_image = cv2.add(hsv_image, array)

print('BGR : \t',origin_image[55,116,:])
print('hsv : \t',hsv_image[55,116,:])
print('hsv 밝기(v) 증가 : \t',val_add_image[55,116,:])

val_add_image = cv2.cvtColor(val_add_image, cv2.COLOR_HSV2BGR)
image = np.concatenate((origin_image,val_add_image), axis=1)

cv2.imshow('add, subtract', image)
cv2.waitKey(0)

  • numpy 를 이용하여 이미지와 shape같은 배열을 생성한 뒤 이미지와 생성된 배열을 합한다 
  • 여기서 중요한 점은 생성한 배열의 dtype이다 
  • imread는 이미지 데이터를 불러올 때 기본 dtype이 uint8로 되어있다 그렇게 때문에 배열을 생성할 때도 dtype을 uint8로 설정해 줘야 더하거나 뺄때 type mismatch가 발생하지 않는다 
  • 강아지 사진을 불러와 HSV 포멧으로 변경한 후 HSV의 V값인 밝기를 100만큼 증가시켰다 
  • 증가시킨뒤 눈으로 확인하기 위해 다시 BGR 포멧으로 변경한 후 imshow 하였다
     
  • 강아지의 눈 부분의 값 변화를 체크해 보겠다
  • 보다시피 HSV 각각에 0, 0, 100의 값을 추가하였기 때문에 밝기 증가 hsv 에서 V의 값만 100이 증가하였다 

3. 특정 부분 이미지 값 변경

  • 이번에는 특정 부분의 밝기만 변경해 보자 
  • 위에서 말했듯이 cv2.add, cv2.subtract 에서는 0이하의 값은 모두 0으로 취급한다 
import cv2
import numpy as np
from matplotlib import pyplot as plt

origin_image = cv2.imread('puppy.jpg')
hsv_image = cv2.cvtColor(origin_image, cv2.COLOR_BGR2HSV)

val = 255

mask = hsv_image[:50,:100,:]

array = np.full(mask.shape, (0,0,val), dtype=np.uint8)

sub_mask_image = cv2.subtract(mask, array)

hsv_image[:50,:100,:] = sub_mask_image

val_sub_image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)

print("원본 bgr \t:",origin_image[0,0,:])
print("변환 bgr \t:",val_sub_image[0,0,:])

image = np.concatenate((origin_image,val_sub_image), axis=1)

cv2.imshow('add, subtract', image)
cv2.waitKey(0)

  • 원본 이미지에서 특정 부분을 선택하여 해당 부분의 HSV- V의 값을 255만큼 뺏다
  • 특정 부분을 다시 원본 이미지에 대입하였다 
  • V의 값이 0이 되었기 때문에 BGR 포멧으로 다시 변환한 후 해당 영역의 값을 확인 해보면 BGR 모두 0이 된것을 확인할 수 있다 

+ Recent posts