본문 바로가기

CV

히스토그램 평활화, 역투영(Equalized, Back-Projection)

1. 히스토그램

- 히스토그램은 해당 값에 대한 빈도수를 시각화하여 나타낸 그래프이다.

- 영상처리에서 히스토그램은 명암값에 대한 빈도수를 나타내기 위해 사용되었다.

- 주로 영상의 특성을 파악하기 위해 사용한다.

더보기

히스토그램의 용도

  1. 영상의 명암값의 분포를 보여준다.
  2. 조작을 통한 영상의 품질을 개선한다.
  3. 컬러 분포가 비슷한 영역을 검출하여 물체를 검출한다.

- 다음 그래프처럼 왼쪽에 치우칠수록 어두운 영상임을 알 수 있다.

- 다음 그래프는 명암의 범위가 넓으며 밝기 분포가 비교적 균일하다.

- 다음 영상의 그래프를 보면 두개의 봉우리가 선명하게 나타난 영상으로 이런 사진은 이진 영상으로 변환하기 쉽다.


히스토그램 OpenCV로 표현하기

- OpenCV와 Matplotlib을 이용하여 Histogram을 찾을 수 있다.

- cv2.calcHist()와 np.histogram()함수를 사용할 수 있다.

 

 

더보기

cv2.calcHist(image,channels,mask,histSize,ranges[,hist[,accumulate]])

 

Parameters

  • image - 분석 대상 이미지. Array형태
  • channels - 분석 채널, 이미지가 grayscale이면 [0], color이미지면 [0]: blue, [1]: green, [2]: red
  • mask - 이미지의 분석 영역, None이면 전체 영역
  • histSize - Bins 값, [256]
  • ranges - Range값, [0,256]

- 다음 예시는 grayscale이미지를 읽어 명암의 분포를 보여주는 예제이다.

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('bwtest.jpg',0)

hist = cv2.calcHist([img],[0],None,[256],[0,256])

plt.subplot(221),plt.imshow(img,'gray')
plt.subplot(223),plt.plot(hist,color='b')
plt.xlim([0,256])
plt.show()

 

 

2. 히스토그램의 평활화 (Histogram Equalized)

- 히스토그램을 조작 및 연산을 통해 영상의 품질을 개선하기도 하는데 가장 대표적인 연산은 히스토그램 평활화 이다.

- 이미지의 히스토그램이 특정 영역에 너무 집중되어 있으면 contrast가 낮아 좋은 이미지라고 할 수 없다. 동적 범위가 골고루 분포 되어 있을때 좋은 이미지라고 할 수 있다.

- 이 연산은 영상의 명암 분포를 평평하게 만든다.

- 연산을 통해 영상의 명암 범위, 즉 동적 범위(Dynamic Range)가 늘어나 영상이 이전보다 선명해진다.

- 주로 명암 분포가 빈약한 영상을 균일하게 하기 위해 사용한다.

영상의 히스토그램이 평활화 되어 왼쪽보다 평평해진 히스토그램이 나온 것을 알 수 있다.

더보기

하지만 histogram equalization은 영상의 명암값의 범위를 stretch하여 이미지를 극적화 시킨것이지

이미지의 진짜 모습이라고 하기는 어렵다.

3. 히스토그램 평활화의 활용 여부

- 히스토그램은 영상의 품질을 개선하기 위해 사용되는 연산이지만, 오히려 품질을 떨어뜨리는 경우도 있다.

- 위 그림은 오히려 히스토그램 평활화가 이미지 품질을 떨어뜨린 사례라고 할 수 있다.

- 새의 깃털 텍스쳐도 훼손되었으며, 특히 시각적인 느낌이 퇴화한 것을 알 수 있다.

- 하지만 새에게 잡아먹히는 곤충의 영상은 오히려 선명해 졌다.

- 새에게 잡아먹히기 직전의 곤충을 확인하는 목적으로 국한한다면, 평활화된 영상이 더 적합하다.

- 용도에 따라 인식하려는 대상의 품질이 더 떨어질 수 있으니 잘 활용해야 한다.

 

5. 히스토그램 평활화 OpenCV를 사용하여 적용해보기

-OpenCV에서는 equalizeHist() 함수를 이용하여 히스토그램 평활화를 진행할 수 있다.

import cv2
import numpy as np
from matplotlib import pyplot as plt


img = cv2.imread('이미지의 저장경로',0);

# OpenCV의 Equaliztion함수
img2 = cv2.equalizeHist(img)
img = cv2.resize(img,(400,400))
img2 = cv2.resize(img2,(400,400))

dst = np.hstack((img, img2))
cv2.imshow('img',dst)
cv2.waitKey()
cv2.destroyAllWindows()

6. CLAHE (Contrast Limited Adaptive Histogram Equalization)

- 위의 히스토그램 평활화는 전체적인 부분에 균일화를 적용하였다.

- 하지만 일반적인 이미지는 밝은 부분과 어두운 부분이 섞여 있기 때문에 전체에 적용하는 것은 그렇게 유용하지 않다.

어두운 부분은 선명해졌지만 원래 밝았던 부분은 오히려 더 품질이 떨어져 보임다.

- 어두운 부분은 균일화가 적용되었지만, 가운데 원래 밝았던 부분은 너무 밝아져 경계선을 알아볼 수 없게 됨.

- 이러한 문제를 해결하기 위해서 adaptive histogram equalization을 적용하게 된다.

- 이미지를 작은 title 형태로 나누어 title 안에서 Equalization을 적용하는 방식이다.

- 하지만 작은 영역으로 나누다 보니 작은 노이즈가 있으면 이것이 반영되어 원하는 결과를 얻을 수 없게 된다.

- 이 문제를 해결하기 위해 contrast limit이라는 값을 적용하여 이 값을 넘어가는 경우 그 영역은 다른 영역에 균일하게 배분하여 적용한다.

import cv2
import numpy as np
from matplotlib import pyplot as plt


img = cv2.imread('images/clahe.png',0);

# contrast limit가 2이고 title의 size는 8X8
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
img2 = clahe.apply(img)

img = cv2.resize(img,(400,400))
img2 = cv2.resize(img2,(400,400))

dst = np.hstack((img, img2))
cv2.imshow('img',dst)
cv2.waitKey()
cv2.destroyAllWindows()

- 결과를 보면 가운데 이미지의 윤곽선도 유지가 되며 전체적인 명암비(contrast)가 높아졌다.

 

아직 공부 안함.

4. 히스토그램 역투영 (Histogram Back-Projection)

- 히스토그램 역투영은 영상의 각 픽셀이 주어진 히스토그램 모델에 얼마나 일치하는지를 검사하는 방법이다.

- 임의의 색상 영역을 검출할때 효과적이다.

- 역투영시 히스토그램은 명암 채널만 사용하는 1차원이 아니라, 최소 2차원 이상을 사용해야 한다.

- 왜냐하면 명암은 조명에 따라 쉽게 변할 뿐만 아니라 얼굴과 비슷한 명암을 갖는 다른 영역이 여러 군데 존재할 가능성이 높아 명암으로 임의의 물체를 검출하기에 어려움이 있다.

 

 

 

역투영은 알파 채널이나 크로마 키 같은 것이 없어도 복잡한 모양의 사물을 분리할 수 있다는 장점이 있습니다. 하지만 역투영은 히스토그램을 기반으로 관심 영역의 색상과 비슷한 물체를 추출하므로, 관심 영역의 색상과 비슷한 다른 물체가 뒤섞여 있을 때는 효과가 떨어질 수 있습니다.