안녕하세요. 지난 포스팅의 Opencv 제대로 쓰기[5].영상 샤프닝에서는 영상으로부터 엣지를 얻은 뒤 샤프닝을 적용하는 방법에 대해서 알아보았습니다. 오늘은 영상으로부터 opencv를 이용해서 히스토그램을 추출하고 히스토그램 평활화하는 방법에 대해서 알아보겠습니다. 오늘도 전체 코드는 아래의 깃허브를 참조해주시길 바랍니다.
skawngus1111/opencv-python-tutorial
Contribute to skawngus1111/opencv-python-tutorial development by creating an account on GitHub.
github.com
가장 먼저 해볼것은 영상으로부터 히스토그램을 추출하는 것입니다. 디지털 영상에서 히스토그램이란 밝기가 어느정도 분포해있는 지 알 수 있는 방법입니다. 이를 통해서 흔히 말하는 영상의 "대비"를 알 수 있습니다. 이에 대한 자세한 내용은 이전에 제가 정리한 링크를 참조해주시길 바랍니다.
디지털 영상 처리 - 영상 히스토그램(Image Histogram)
안녕하세요. 지난 포스팅에서는 디지털 영상 처리 - 밝기 변환 함수에 대해서 알아보았습니다. 그 중에서도 대표적인 변환인 영상 반전, 영상 로그 변환, 감마 변환 등을 직접 매트랩 코드를 이
everyday-image-processing.tistory.com
opencv에서는 히스토그램을 추출하는 함수인 cv2.calcHist(images, channels, mask, histSize, ranges)를 지원하고 있습니다. 각 파라미터의 의미를 알아보도록 하겠습니다.
- images(array) : 히스토그램을 추출할 영상
- channels(int) : RGB 영상과 같은 경우 어떤 채널에서 히스토그램을 얻을 것 인지
- mask(array) : 영상에서 특정 영역에 대한 히스토그램을 추출하고 싶다면 영상과 동일한 사이즈의 마스크를 만들어서 입력으로 넣어주기.
- histSize(int) : 히스토그램의 $X$축의 길이. 즉 bin의 갯수와 동일
- ranges(array) : 영상에서 히스토그램을 추출한 강도의 범위
예를 들어서 cv2.calcHist(images, [0], None, [256], [0, 256])은 입력 영상 images에 대해서 첫번째 채널(0)에 대해서 마스크를 적용하지 않고(None) 히스토그램 bin의 개수는 256으로 픽셀 강도는 0부터 255까지 추출하겠다는 의미와 동일합니다. 간단하게 예를 보도록 하겠습니다.
light_image = cv2.imread('./example/Ch3/Fig0320(1)(top_left).tif')
gray_image = cv2.imread('./example/Ch3/Fig0320(2)(2nd_from_top).tif')
high_cont_image = cv2.imread('./example/Ch3/Fig0320(3)(third_from_top).tif')
dark_image = cv2.imread('./example/Ch3/Fig0320(4)(bottom_left).tif')
light_hist = cv2.calcHist(light_image, [0], None, [256], [0, 256])
gray_hist = cv2.calcHist(gray_image, [0], None, [256], [0, 256])
high_cont_hist = cv2.calcHist(high_cont_image, [0], None, [256], [0, 256])
dark_hist = cv2.calcHist(dark_image, [0], None, [256], [0, 256])
위의 결과를 보도록 하겠습니다. 가장 왼쪽 영상은 다른 영상들에 비해서 굉장히 밝다는 것을 알 수 있습니다. 그리고 그에 대응되는 히스토그램 분포를 보면 전체적으로 100 이상의 영역에 분포해있다는 것을 알 수 있죠. 그리고 두번째 영상은 경계와 객체가 크게 뚜렸하지 않은 저대비 영상입니다. 그리고 그 히스토그램은 아주 좁은 영역에 분포해있죠. 그에 반해 세번째 영상은 고대비 영상입니다. 히스토그램을 보면 두번째 영상의 히스토그램과 비교해보았을 때 전체적으로 분포하고 있음을 알 수 있죠. 마지막 영상은 어두운 영상이기 때문에 히스토그램이 전체적으로 100보다 작은 영역에 분포해있다는 것까지 예측을 할 수 있습니다. 저희의 목표는 고대비 영상을 만드는 것입니다. 따라서 영상의 히스토그램을 변환했을 때 전체적으로 분포할 수 있도록 만드는 알고리즘이 필요하죠. 이러한 알고리즘을 "히스토그램 평활화(Histogram Equalization)"이라고 합니다. 이에 대한 수학적 알고리즘은 아래의 링크를 참조하고 여기서는 생략하도록 하겠습니다.
디지털 영상 처리 - 히스토그램 평활화(histogram equalization)
안녕하세요. 지난 포스팅의 디지털 영상 처리 - 영상 히스토그램(image historgram)에서는 영상을 히스토그램으로 변환하였을 때 밝기와 대비에 따른 히스토그램의 분포의 차이를 알아보았습니다.
everyday-image-processing.tistory.com
물론 opencv에서는 히스토그램 평활화를 위한 cv2.equalizeHist(img) 역시 제공하고 있습니다. 단순히 입력 영상만 넣어주면 알아서 평활화된 영상이 나오기 때문에 아주 간편한 함수입니다. 다만 입력 영상이 단채널 영상이여야만 합니다. 이 부분만 잘 신경써주시면 됩니다.
image = cv2.imread('./example/low_cont.jpg', cv2.IMREAD_GRAYSCALE)
hist = cv2.calcHist(image, [0], None, [256], [0, 256])
histeq_image = cv2.equalizeHist(image)
histeq_image_hist = cv2.calcHist(histeq_image, [0], None, [256], [0, 256])
입력 영상이 150 근처의 픽셀 강도로 집중되어있었으나 히스토그램 평활화 함수를 적용한 결과 아래와 같이 비교적 넓게 분포된 영상을 얻을 수 있습니다.
'Programming > Python' 카테고리의 다른 글
MMCV Segmentation 입문기 2 (0) | 2022.12.02 |
---|---|
MMCV Segmentation 입문기 1 (0) | 2022.12.02 |
Opencv 제대로 쓰기[5].영상 샤프닝 (0) | 2021.05.31 |
Opencv 제대로 쓰기[4].흐림 처리 (0) | 2021.05.23 |
Opencv 제대로 쓰기[3].외부 카메라 동영상 스크린샷 저장하기 (0) | 2021.05.01 |