앞서 [Python 영상처리 기초 4] 이미지의 픽셀값 다루기 - Crop, 선형연산 에서 보았듯이,
픽셀값을 증가시키면 이미지의 밝기가 밝아짐을 알 수 있습니다.
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img_color = cv2.imread('national-cancer-institute-jdfn7Z03Qa4-unsplash.jpg',cv2.IMREAD_COLOR)
img_gray = cv2.cvtColor(img_color,cv2.COLOR_BGR2GRAY)
start_pt = [1210, 753] # [y, x-axis] or (y, x-axis), both are fine
end_pt = [2110, 2115] # [y, x-axis]
img_gray_crop = img_gray[start_pt[0]:end_pt[0], start_pt[1]:end_pt[1]] # numpy slicing
img_gray_crop_UP = (img_gray_crop * 1.7).astype('uint8') # intensity 70% UP
단순히 픽셀값을 증가시킨다면 이미지의 Global 픽셀값들이 증가하므로 원하지 않는 결과를 얻을 수
있습니다. 예를들어 ROI (region of interest) 의 픽셀값 분포가 높거나 낮은 intensity에 집중분포해
있다면 이 영역만을 확장시켜 주어 밝기나 컨트래스트를 개선할 수 있지만, 전 영역의 픽셀값을 증가시키면
그저 빛바랜 듯한 이미지 결과가 나오기도 합니다.
이미지의 brightness와 contrast는 다음의 수식 (출처 1)을 통해 조절할 수 있습니다.
g(i, j) = alpha · f(i, j) + beta
입력 이미지 f( i 번째 행, j 번째 열 ) 는 alpha와 beta - 각각 gain과 bias로 불리며 contrast와 brightness
를 제어하는 파라메터 - 값에 의한 연산으로 결과 이미지 g( i, j ) 를 얻습니다.
위 식에서 beta값을 증가 또는 감소시키면 - 맨 위의 이미지의 밝기가 70% 향상된 예와같이 - 대상 이미지의
brightness가 밝아지거나 어두워질 수 있으며, alpha는 대상 이미지 픽셀 분포를 확장 또는 압축하는 역할을
합니다.
다음은 Brightness-Contrast-Gamma의 관계를 보여주는 그래프이며 이해를 돕는 설명들이 출처 2 에
담겨있으므로 한번쯤 읽어 보시길 바랍니다. 여기에서 gamma란 입력 이미지를 매핑하는 곡선의 모양을 정의
하는 값으로써 나중에 후술하겠습니다. 밑의 그래프에 관해 간략히 설명하자면 입력 gray level 과 출력 gray
level의 매핑을 보여주는 그래프들로써 빨간색 선의 증감에 따라 brightness 가 밝아지거나 어두어짐을
나타내고 빨간색 선의 기울기에 따라 contrast의 증감을 보여줍니다. Gamma의 첫번째와 두번째 그래프와
같이 빨간색 선이 어두운 영역에서 급격히 증가하면 (gamma < 1) 어두운 영역의 픽셀 분포가 확장되어
이 영역의 가시성(visible)이 좋아지는 효과가 있습니다.
이미지 픽셀값 변환에서 Brightness와 contrast 는 뗄수 없는 관계이고, 항상 선형적인 상관관계를
갖지도 않습니다. 그러므로 alpha에 의해 contrast가 조정됨과 동시에 brightness가 달라질 수 있고,
반대의 경우도 가능합니다.
입력 이미지가 gray scale 2차원의 경우, 위 수식에 따라 x, y축 (혹은 i, j 방향)에 따라 2번의 for loop
연산을 수행해야 하지만 - 3차원의 컬러 이미지는 3번의 for loop 필요 - 효율적인 연산을 위해 OpenCV
가 제공하는 convertScaleAbs( ) 메소드를 이용해 이미지의 brightness, constrast를 변환해 보겠습니다.
입력 이미지는 다음과 같고 gray scale 이미지로 변환하여 이용할 것입니다.
밑의 이미지는 본 블로그 맨밑 출처 3에 가셔서 다운로드 받을 수 있습니다.
다음은 brightness 변환의 결과를 보여줍니다. 입력 이미지는 uint8 타입으로써 최소 0, 최대 255의 픽셀값
범위를 가지며, 위의 변환수식중 임의값 beta = 30 으로 대상 이미지의 brightness를 향상시켰고, 밑의
brightness 변환 전후의 histogram를 비교해보면 그래프의 피크가 좌측에서 우측으로 대략 30만큼 이동
했음을 알 수 있습니다.
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img_color = cv2.imread('national-cancer-institute-jdfn7Z03Qa4-unsplash.jpg',cv2.IMREAD_COLOR)
img_gray = cv2.cvtColor(img_color,cv2.COLOR_BGR2GRAY)
alpha = 1 # contrast control
beta = 30 # brightness control
img_beta_UP1 = cv2.convertScaleAbs(img_gray, alpha=alpha, beta=beta)
img_gray_hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256])
img_beta_UP1_hist = cv2.calcHist([img_beta_UP1], [0], None, [256], [0, 256])
fig = plt.figure(figsize=(12,10))
fig.add_subplot(2,2,1)
plt.axis("off")
plt.title("Original")
plt.imshow(img_gray,cmap='gray')
fig.add_subplot(2,2,2)
plt.axis("off")
plt.title("Brightness raised")
plt.imshow(img_beta_UP1,cmap='gray')
fig.add_subplot(2,2,3)
plt.plot(img_gray_hist)
plt.xlim([0, 256])
fig.add_subplot(2,2,4)
plt.plot(img_beta_UP1_hist)
plt.xlim([0, 256])
plt.show()
또 다른 beta값으로써 입력 이미지 픽셀의 평균값 46.466 (uint8 타입 - 최소0, 최대 255)에 70%를
상향시켜 적용한 결과 입니다. 밑 우측의 histogram에서 보듯이 낮은 영역에 존재하던 피크가 대략
픽셀값 100 으로 이동했음을 알 수 있습니다.
alpha = 1 # contrast control
beta = np.mean(img_gray)*1.7 # brightness control
img_beta_UP2 = cv2.convertScaleAbs(img_gray, alpha=alpha, beta=beta)
img_gray_hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256])
img_beta_UP2_hist = cv2.calcHist([img_beta_UP2], [0], None, [256], [0, 256])
fig = plt.figure(figsize=(12,10))
fig.add_subplot(2,2,1)
plt.axis("off")
plt.title("Original")
plt.imshow(img_gray,cmap='gray')
fig.add_subplot(2,2,2)
plt.axis("off")
plt.title("Brightness raised")
plt.imshow(img_beta_UP2,cmap='gray')
fig.add_subplot(2,2,3)
plt.plot(img_gray_hist)
plt.xlim([0, 256])
fig.add_subplot(2,2,4)
plt.plot(img_beta_UP2_hist)
plt.xlim([0, 256])
plt.show()
출처1: https://docs.opencv.org/3.4/d3/dc1/tutorial_basic_linear_transform.html
OpenCV: Changing the contrast and brightness of an image!
Prev Tutorial: Adding (blending) two images using OpenCV Next Tutorial: Discrete Fourier Transform Goal In this tutorial you will learn how to: Access pixel values Initialize a matrix with zeros Learn what cv::saturate_cast does and why it is useful Get so
docs.opencv.org
출처2: https://www.quora.com/What-is-the-difference-between-brightness-contrast-and-gamma
What is the difference between brightness, contrast, and gamma?
Answer (1 of 4): Not all definitions are the same, but due to tradition from television set controls, this is how they are defined in display technology. Brightness is simply a DC offset. An amount of uniform light added to (or subtracted from) everything
www.quora.com
출처3: https://unsplash.com/photos/jdfn7Z03Qa4
사진 작가: National Cancer Institute, Unsplash
Cells from cervical cancer – Splash에서 National Cancer Institute의 이 사진 다운로드
unsplash.com
'Python 영상처리 기초 with OpenCV' 카테고리의 다른 글
[Python 영상처리 기초 8] Affine Transformations (0) | 2023.09.25 |
---|---|
[Python 영상처리 기초 7] 이미지의 화질개선 Contrast-Brightness-Gamma - part2 (0) | 2023.09.17 |
[Python 영상처리 기초 6] 선형 공간 필터링 - Average, Laplacian, Sobel filters (0) | 2023.08.08 |
[Python 영상처리 기초 5] 이미지의 화질개선 - Normalization, Standardization (1) | 2023.08.02 |
[Python 영상처리 기초 4] 이미지의 픽셀값 다루기 - Crop, 선형연산 (2) | 2023.07.31 |