OpenCV 2: 이미지의 기초 및 기본연산을 활용한 이미지 밝기, 명암 조절

이미지 배열 기초

OpenCV로 읽어들인 이미지 배열의 구조와 인덱싱, 색상채널 분리 등에 대하여 간단히 정리한다.

OpenCV의 이미지 배열은 numpy의 배열과 유사한 객체로써, numpy 배열의 메서드들도 함께 제공된다.

이미지 배열의 구조
  • 이미지객체.shape: 이미지 객체의 속성(세로, 가로, 색상 반환)
  • 이미지객체.size: 이미지의 전체 픽셀 수 반환
  • 이미지객체.dtype: 이미지의 픽셀을 표현하는 값의 데이터타입 반환
import cv2
img = cv2.imread('a.jpg', 1)
h, w, c = img.shape
print('세로:', h, '가로:', w, '색상:', c)
세로: 427 가로: 640 색상: 3
  • 정리하면, 이미지는 2차원 배열 + 값마다 b,g,r의 3가지 값의 배열이 들어가 있는 3차원 배열이다.


이미지 특정 픽셀 인덱싱
  • 이미지객체[y, x]
# 이미지 특정 픽셀 인덱싱
img = cv2.imread('a.jpg', 1)
h, w, c = img.shape
print('세로:', h, '가로:', w, '색상:', c)
p = img[100, 100]
p
array([111, 131, 132], dtype=uint8)


이미지 특정 영역 인덱싱
roi = img[100:200, 100:300] # h: 100~200, w: 100~300


특정 픽셀값 지정하여 변경하기
  • 이미지객체[y, x] = val
img[100, 100] = [255,255,255] #(100,100)위치의 픽셀을 흰색으로 변경
cv2.imshow('img', img) # 하얀 점이 찍혀있는지 확인
cv2.waitKey(0)
cv2.destroyAllWindows()


특정 픽셀의 특정 색상값 반환
  • 이미지객체.item(y, x, c)
    • 해당 좌표의 c 색상값을 반환
p2 = img.item(100, 100, 2) # (100,100)의 r채널 값
p2
255 # 앞서 해당 픽셀을 [255,255,255]로 변경한 바 있다.


이미지의 특정 색상채널 분리
img_blue = img[:,:,0] # 이미지 전체의 b 색상채널
img_blue = img[:,:,1] # 이미지 전체의 g 색상채널
img_blue = img[:,:,2] # 이미지 전체의 r 색상채널


이미지 color-space 변환
  • cv2.cvtColor(원본이미지, type)
    • type: 칼라→흑백, BGR→RGB, RGB→BGR 등
src = cv2.imread('a.jpg')
img1 = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # BGR칼라 → graycale
img2 = cv2.cvtColor(src, cv2.COLOR_BGR2RGB) # BGR칼라 → RGB칼라
img3 = cv2.cvtColor(img2, cv2.COLOR_RGB2BGR) # RGB칼라 → BGR칼라


이미지 연산(밝기, 명암 조절)

이미지 밝기 조절(+, - 이용)
import numpy as np

def saturate_bright(p, num): # num 만큼 색상값 증가(밝게하기)
    pic = p.copy()
    pic = pic.astype('int32') # 연산전에 dtype을 32비트짜리로 넉넉하게 바꾼다.
    pic = np.clip(pic+num, 0, 255) # 포화연산: 연산 결과 0미만 값은 0, 255 초과 값은 255로 변경
    pic = pic.astype('uint8')
    return pic

def saturate_dark(p, num): # 감소(어둡게 하기)
    pic = p.copy()
    pic = pic.astype('int32')
    pic = np.clip(pic-num, 0, 255)
    pic = pic.astype('uint8')
    return pic
img2 = saturate_bright(img, 100)  # 픽셀값 100만큼 이미지 밝게 처리
img3 = saturate_dark(img, 100)  # 픽셀값 100만큼 이미지 어둡게 처리


이미지 명암 조절(+,-,* 등 이용)
  • 픽셀값이 큰 부분(밝음)과 작은 부분(어두움)의 차이를 더욱 크게 하면 명암비가 커진다.
  • 명암비가 커질수록 선명해보이는 효과
# 픽셀값에 배수를 곱하여 차이를 더 크게 하는 함수
def saturate_contrast1(p, num):
    pic = p.copy()
    pic = pic.astype('int64')
    pic = np.clip(pic*num, 0, 255) # 특정 배율을 곱해줌으로써 명암비 조절(색상값 증폭)
    pic = pic.astype('uint8')
    return pic

# 픽셀값 중간인 128을 기준으로, 이보다 어두우면 더 어둡게, 밝으면 더 밝게 조절
def saturate_contrast2(p, num):
    pic = p.copy()
    pic = pic.astype('int32')
    pic = np.clip(pic+(pic-128)*num, 0, 255)
    pic = pic.astype('uint8')
    return pic


기타: 이미지 위에 도형 그리기

이미지 원본 위에 임의로 도형이나 텍스트상자를 그릴 수도 있다.

다음에 간단히 정리한다.

* 선 그리기 - cv2.line(선을그릴이미지경로, 선의 시작점(x,y)좌표, 끝점좌표, 선의색상, 선의 두께)

* 사각형 - cv2.rectangle(이미지, 시작점,끝점,색상,두께)

* 원 - cv2.circle(이미지, 중심점, 반지름,색상,두께)

* 타원 - cv2.ellipse(이미지, 중심점, 중심점에서 가장큰거리와 작은거리, 타원의 기울기 각, 타원 시작각도, 타원끝각도, 색상, 두께)

* 다각형 - cv2.polyline(이미지, 점들,닫힘여부(True or False), 색상, 두께)

* 텍스트상자 - cv2.putText(이미지, 텍스트, 위치, 폰트, 글자크기, 색상)

Leave a comment