OpenCV - 기본적인 이미지 처리

2 분 소요

OpenCV 컬러 변환

일반적으로 컴퓨터에서 컬러를 표현할 때 [r,g,b] 순으로 표현하지만 OpenCV는 [b, g, r] 순으로 표현한다. 그래서 외부에서 이미지를 가져와서 OpenCV로 출력하거나, OpenCV로 읽어들인 이미지를 matplot 등을 통해 표현하려면 색상 순서를 변환해줘야한다.

cv2.merge() 를 사용한 변환

#opencv로 읽은 이미지, 현재 [b,g,r] 순으로 되어있음
img = cv2.imread('a.jpg', cv2.IMREAD_COLOR)

#opencv로 읽은 이미지의 r,g,b순서를 뒤집어 배열
b, g, r = cv2.split(img)   # img파일을 b,g,r로 분리
img2 = cv2.merge([r,g,b]) # b, g, r을 [r,g,b]로 Merge 하여 이미지 생성

cv2.cvtColor() 를 사용한 변환

img = cv2.imread('a.jpg') # 현재 [b,g,r]
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  #bgr에서 rgb로 변환하여 이미지 생성
img3 = cv2.cvt.Color(img2, cv2.COLOR_RGB2BGR)  #rgb에서 다시 bgr로 변환하여 이미지 생성

컬러 이미지를 그레이스케일로 변환

# 이미지 파일 불러올 때 그레이스케일로 불러오기
gray_img = cv2.imread('a.jpg', 0)
gray_img2 = cv2.imread('a.jpg', cv2.IMREAD_GRAYSCALE)

#cvtColor()로 그레이스케일로 변환
gray_img3 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

이미지 정보 확인

이미지 세로, 가로, 채널 확인 (.shape)

img = cv2.imread('a.jpg')
img.shape
>>> 427, 640, 3  # h(높이), w(너비), c(색상 채널 수) 순
h, w, c = img.shape  # h, w, c 변수에 각각 높이, 너비, 채널 수 값을 입력

이미지 데이터 수 확인 (.size)

img = cv2.imread('a.jpg')
img.size
>>> 819840  # h*w*c

이미지 표현 데이터 타입 (.dtype)

img = cv2.imread('a.jpg')
img.dtype
>>> dtype('uint8')

픽셀 추출, 확인 및 변경

특정 픽셀 추출

p = img[100, 100]  #(100, 100) 위치의 픽셀 한 개 추출
print(p)
>>> [134, 156, 219]  # 픽셀의 값, [b, g, r] 

픽셀 정보 확인 (.item)

#픽셀의 한 채널의 값
p = img[100, 100, 2]  # 0:b, 1:g, 2:r
print(p)
>>> 219

#.item 사용
p2 = img.item(100, 100, 2)  # 픽셀의 red 값 반환, 반드시 채널 인자까지 입력해야 함
print(p2)
>>> 219

픽셀 값 변경 (.itemset)

# (100, 100) 위치의 픽셀을 흰색으로 변경
img[100, 100] = [255, 255, 255]

# .itemset 사용, 픽셀을 검은색으로 변경
img.itemset((100, 100, 0), 0)
img.itemset((100, 100, 1), 0)
img.itemset((100, 100, 2), 0)

ROI (Region of Image)

이미지의 특정 영역을 지정하여 추출할 때 사용

# roi = 이미지[ y시작점 : y끝점, x시작점 : x끝점 ]
roi = img[100:200, 100:300]
cv2.imshow('roi', roi)
cv2.waitKey(0)
cv2.destroyAllWindows()

이미지 채널 분리

cv2.split() 을 통한 분리

b, g, r = cv2.split(img)
img = cv2.merge((r,g,b))  # bgr-to-rgb
  • 간단하지만 이미치 처리 비용이 비싸기 때문에 numpy 인덱싱으로 접근하는 것이 효과적이다.

numpy 인덱싱을 통한 분리

색상채널 0:blue, 1:green, 2:red

# 이미지에서 특정 색상 추출. 이미지 전체를 roi로 지정하여 데이터 추출
img_blue = img[:, :, 0]
img_green = img[:, :, 1]
img_red = img[:, :, 2]

# 이미지에서 특정 색상 제거
img[:, :, 2] = 0   # img에서 빨간색 제거

이미지 복사

src = cv2.imread('a.jpg')
img1 = src  # 얕은복사, src의 데이터 참조 주소만을 img1에 입력
img2 = src[100:200, 100:200]  # 얕은복사
img3 = src.copy()  # 깊은복사

img1[100:200, 100:200, 2] = 255  # img1의 특정 지역을 roi로 정하여 색상 변경
  • 위 코드를 실행하고나면 img1에 복사된 참조주소의 데이터가 영향을 받으므로 img1과 함께 src의 색상도 변경된다.
  • roi를 통해 일부 영역만 복사한 img2 역시 얕은 복사가 되었기 때문에 영향을 받는다.
  • 하지만 img2는 깊은 복사를 하여 별도의 데이터 주소를 가졌기 때문에 영향을 받지 않는다.

댓글남기기