파이썬 기초(1일 1코드)

파이썬 시각화 공부 7일(이미지 히스토그램(histogram) 그리기)

공대아저씨 2023. 9. 13. 22:15

안녕하세요 공대아저씨 입니다. 

오늘은 파이썬 시각화 공부 7일차로 이미지를 히스토그램으로 그리는 것을 해보려고합니다.

 

이미지를 히스토그램으로 그리는 이유는 이미지의 픽셀에 대한 강도, 분포를 그래프로 나타냄으로써

이미지의 정보를 시각화 하고 분석하기 위해서입니다.

 

좀더 자세히 알아보자면,

 

1. 이미지 특성 파악 : 히스토그램을 통해 미지의 밝기 또는 색상 분포를 시각적으로 파악할 수 있습니다. 이를 통해 이미지의 주요 특성을 빠르게 파악할 수 있습니다. 예를 들어, 이미지가 밝거나 어두운 영역이 얼마나 많은지를 확인할 수 있습니다.


2. 대조 및 밝기 조절 : 히스토그램을 분석하여 이미지의 대조도를 평가하고 조절할 수 있습니다. 대조도가 낮은 이미지는 히스토그램이 좁게 분포되어 있고, 대조도가 높은 이미지는 히스토그램이 넓게 분포됩니다. 대조도를 조절하여 이미지를 더 선명하게 만들 수 있습니다.

3. 이미지 분류 및 검색 : 이미지의 히스토그램은 이미지 간 유사성을 측정하는 데 사용될 수 있습니다. 비슷한 히스토그램을 가진 이미지는 유사한 시각적 특성을 공유할 가능성이 높습니다. 따라서 이미지 분류 및 검색에 유용한 지표로 활용됩니다.

4. 이미지 전처리 : 이미지를 처리하기 전에 히스토그램을 분석하여 전처리 작업을 수행할 수 있습니다. 예를 들어, 이미지의 밝기나 색상을 조정하기 위해 히스토그램 평활화(Histogram Equalization)를 사용할 수 있습니다.

5. 이미지 품질 평가 : 이미지의 히스토그램을 분석하여 이미지 품질을 평가할 수 있습니다. 히스토그램을 통해 이미지의 대비, 밝기 분포, 색조 등과 관련된 문제를 식별하고 해결할 수 있습니다.

 

자, 그럼 이미지를 어떻게 히스토그램으로 표현하는지 한번 해보겠습니다.

 

fruits2.jpg
0.17MB

실습 이미지를 다운받으시기 바랍니다.

 

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('./img/fruits2.jpg')

print ('img', img.shape, img.dtype)
print ('img.ravel()', img.ravel().shape, img.ravel().dtype)
print (734*1100*3)

plt.hist(img.ravel(), 255, [0,255])
plt.xlim([0,256])
plt.show()

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

plt.plot(hist)
plt.xlim([0,256])
plt.show()

이미지를 그냥 cv2 코드를 이용해서 읽어오면 이미지의 크기와 색깔에 따른 행렬로 표현이 됩니다.

그렇게 행렬로 표현된 값들은 1차원으로 펼쳐주어야 어떤 값들이 자주나왔는지 히스토그램을 그릴때 제대로 카운팅을 할 수 있습니다. 

 

그래서 img.ravel()코드를 통해서 1차원 배열로 변환 합니다.

또한,  히스토그램의 bin 수를 255로 지정합니다. 히스토그램 범위는 [0, 255]로 설정되며, plt.xlim()으로 x축의 범위를 지정합니다. 마지막으로 plt.show()로 히스토그램을 표시합니다.

 

그러면 다음과 같은 결과가 나옵니다.

 

빨간색에 대한 분포

 

이번엔 각 채널에 대한 히스토그램을 for 함수를 통해서 구현해보도록 하겠습니다.

 

car_plate.jpg
0.24MB

실습이미지는 이것을 사용하세요 :)

 

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('./img/car_plate.jpg')
splits = cv2.split(img)

for i in splits:
    hist = cv2.calcHist(i, [0], None, [256], [0, 256])
    plt.plot(hist)
    plt.xlim([0,256])

plt.show()

이 코드가 다른 것은 바로 for 함수를 사용한 점입니다.

for 함수를 사용하여 splits 리스트에 있는 각 채널(B, G, R)에 대해 히스토그램을 계산하고 그립니다.

그리고, cv2.calcHist() 함수를 사용하여 히스토그램을 계산하며, [0]은 채널 인덱스를 나타내고

[256]은 히스토그램의 bin 수를 지정하고, [0, 256]은 히스토그램 범위를 나타냅니다.

 

for 함수를 통해 여러채널 히스토그램 그리기

자, 이와 같이 이미지를 히스토그램으로 표현한 것을 볼 수 있습니다.

그래프를 보니까 b,g,r 3개의 채널에 대한 값이 모두 0~50 사이의 값이 굉장히 많이 분포된 것으로 보았을때,

이미지에 여러가지 색이 있는 것이 아니라 몇가지 색으로 이루어진 단조로운 이미지 인 것을 

히스토그램을 통해서도 알수 있습니다.

 

자, 이번시간에는 단순한 이미지를 갖고 히스토그램으로 표현을 하고 어떻게 해석하는지

그리고 이미지를 히스토그램으로 표현하는 것이 왜 필요한지에 대해서 알아보았습니다.

 

다음시간에는 원본이미지 + 스케일을 변환한 이미지의 히스토그램을 같이 비교하면서

어떤 차이가 발생하는지에 대해서 한번 알아보도록 하겠습니다.

 

긴 글을 읽어 주셔서 감사합니다. :)