영상 내 개별 화소(Pixel) 데이터 접근법 및 산술 연산을 통한 밝기 제어
OpenCV 영상은 결국 uint8 형식을 갖는 행렬이다. 이 행렬의 각 원소(화소) 값을 수정하면 영상의 밝기를 밝게 하거나 어둡게 만들 수 있다.
1. 화소 접근 (Pixel Access)
배열 인덱싱: img[y, x] 형태로 특정 위치의 픽셀 값에 접근한다.
BGR 구조: 컬러 영상의 경우 img[y, x]는 [B, G, R] 세 개의 값을 가진 리스트 형태다.
2. 밝기 조절 (Brightness)
영상의 모든 화소에 일정 값을 더하면 밝아지고, 빼면 어두워진다.
Overflow 주의: uint8 자료형은 ~ 사이만 표현한다. 이 이 아닌 (나머지값)가 되지 않도록 포화 연산(Saturation) 처리가 필수다.
3. 명암비(Contrast) 조절
영상의 밝은 부분과 어두운 부분의 차이를 크게 만드는 것이다.
보통 픽셀 값에 특정 상수를 곱하여 조절한다.
영상의 밝기를 전체적으로 높이고, 포화 연산을 적용하는 실습.
1. 밝기 조절 및 산술 연산 (brightness_test.py)
Python
import cv2
import numpy as np
# 영상 불러오기 (Grayscale로 테스트)
src = cv2.imread('lenna.jpg', cv2.IMREAD_GRAYSCALE)
if src is None:
print("이미지를 찾을 수 없습니다.")
exit()
# 1. 단순 더하기 (Numpy 연산 - Overflow 위험 있음)
# 255를 넘어가면 다시 0부터 시작해서 이상한 무늬가 생김
dst_bad = src + 100
# 2. OpenCV 포화 연산 함수 사용 (권장)
# 255를 넘으면 255로 고정해줌
dst_good = cv2.add(src, 100)
# 3. 명암비 조절 (픽셀 값에 2.0 곱하기)
dst_contrast = cv2.multiply(src, 2.0)
cv2.imshow('Original', src)
cv2.imshow('Bad Brightness (Numpy)', dst_bad)
cv2.imshow('Good Brightness (OpenCV)', dst_good)
cv2.imshow('Contrast High', dst_contrast)
cv2.waitKey(0)
cv2.destroyAllWindows()
Numpy 연산 vs OpenCV 함수: src + 100처럼 넘파이 배열 연산을 직접 쓰면 를 초과할 때 값이 튀어버리는(Modulo 연산) 현상이 발생한다. 영상 처리를 할 때는 반드시 cv2.add()나 np.clip()을 사용해 값을 가둬줘야 한다는 점을 배웠다.
데이터 타입: 연산 과정에서 일시적으로 를 넘거나 음수가 될 수 있으므로, 복잡한 연산 시에는 float32로 변환했다가 다시 uint8로 바꾸는 과정이 필요할 수 있음을 알게 되었다.
영상의 밝기는 화소 값의 덧셈/뺄셈, 명암비는 곱셈으로 조절한다.
값의 범위가 ~ 를 벗어나지 않도록 포화 연산(Saturation)을 적용해야 한다.
OpenCV의 cv2.add(), cv2.subtract() 함수는 내부적으로 포화 연산을 처리해준다.