파이썬으로 영상 다루기 첫걸음
OpenCV는 실시간 컴퓨터 비전과 이미지 처리를 위한 오픈소스 라이브러리다. 파이썬에서는 cv2 모듈로 이미지·영상 읽기, 변환, 필터링, 객체 검출 등을 할 수 있고, NumPy와 호환되어 배열 연산으로 빠르게 처리할 수 있다. 이번 포스트에서는 OpenCV 버전 확인부터 이미지 읽기(그레이스케일/컬러), 이미지 속성과 NumPy 배열, 도형 그리기와 마우스 이벤트까지 네 개의 실습 파일을 기준으로 한 번에 정리한다.
(OpenCV - 류지 프로젝트에서 개념 설명을 참고하여 재구성)
1. OpenCV 설치 및 버전 확인
OpenCV를 쓰려면 opencv-python 패키지를 설치한 뒤, 버전을 확인하면 된다.
pip install opencv-python
실습 코드에서는 cv2.__version__으로 현재 설치된 OpenCV 버전을 출력한다.
import cv2
print('OpenCV Version: ', cv2.__version__)
※ OpenCV란?
OpenCV(Open Source Computer Vision Library)는 실시간 컴퓨터 비전 및 이미지 처리를 위한 오픈소스 라이브러리다. Python에서 cv2 모듈을 통해 사용할 수 있으며, 이미지·영상의 읽기, 변환, 필터링, 객체 검출, 특징 추출 등을 제공한다. NumPy와 호환성이 좋아 배열 연산을 활용한 고속 이미지 처리가 가능하고, 머신러닝·딥러닝 모델과도 쉽게 연동된다. 얼굴 인식, 객체 추적, AR, 자율 주행 등에서 널리 쓰인다.
2. 이미지 읽기 - 그레이스케일과 컬러, BGR과 RGB
이미지 파일을 읽을 때는 cv2.imread()를 사용한다. 그레이스케일로 읽을지 컬러로 읽을지 플래그로 지정하고, OpenCV는 컬러 이미지를 BGR 순서로 읽는다는 점을 알아 두면 Matplotlib 등과 연동할 때 편하다.
2-1. imread와 플래그
cv2.IMREAD_GRAYSCALE: 1채널 흑백(그레이스케일)로 읽는다.cv2.IMREAD_COLOR: 3채널 컬러(BGR)로 읽는다. 기본값이라 생략 가능하다.
import cv2
import matplotlib.pyplot as plt
img1 = cv2.imread('./images/dog.bmp', cv2.IMREAD_GRAYSCALE)
print(img1)
# RGB가 아니고 BGR로 알아서 읽음
img2 = cv2.imread('./images/dog.bmp', cv2.IMREAD_COLOR) # cv2.IMREAD_COLOR는 생략 가능
img_color = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) # BGR -> RGB 순서를 읽을 수 있게 컨버팅
plt.subplot(121) # plt.subplot(1, 2, 1)
plt.axis('off')
plt.imshow(img1, cmap='gray')
plt.subplot(122) # plt.subplot(1, 2, 2)
plt.axis('off')
plt.imshow(img_color)
plt.show()
그레이스케일은 plt.imshow(img1, cmap='gray')로, BGR을 RGB로 바꾼 img_color는 plt.imshow(img_color)로 그리면 색이 올바르게 나온다.
※ 그레이스케일 영상
그레이스케일(Grayscale) 영상은 흑백 영상으로, 각 픽셀이 밝기 정보만 갖는 1채널 영상이다. 보통 0(검은색)~255(흰색) 사이 값으로 표현되고, RGB 영상에서 색상 정보를 제거하고 밝기만 남기는 방식으로 변환할 수도 있다. 엣지 검출, 객체 인식, 얼굴 탐지 등에서 연산량을 줄이기 위해 자주 쓴다.
※ 트루컬러(BGR) 영상
OpenCV가 읽는 컬러 영상은 BGR 3채널이다. 각 픽셀은 (B, G, R) 조합으로 표현되고, 채널당 0~255 범위를 가진다. Matplotlib의 imshow는 RGB 순서를 기대하므로, cv2.cvtColor(img, cv2.COLOR_BGR2RGB)로 바꾼 뒤 표시하는 것이 좋다.
3. 이미지 속성과 NumPy 배열, 키보드 이벤트
cv2.imread()로 읽은 이미지는 NumPy 배열이다. shape, dtype으로 크기와 채널, 데이터 타입을 확인할 수 있고, np.zeros, np.ones, np.full로 빈 영상·단색 영상을 만들 수 있다. 창을 띄운 뒤에는 cv2.waitKey()로 키 입력을 받아 반전·종료 같은 동작을 줄 수 있다.
3-1. type, shape, dtype
그레이스케일은 (높이, 너비), 컬러는 (높이, 너비, 채널) 형태다. dtype은 보통 uint8이다.
import cv2
import numpy as np
img_gray = cv2.imread('./images/dog.bmp', cv2.IMREAD_GRAYSCALE)
print('img_gray type: ', type(img_gray)) # <class 'numpy.ndarray'>
print('img_gray shape: ', img_gray.shape) # (364, 548) 세로, 가로
print('img_gray dtype: ', img_gray.dtype) # uint8
img_color = cv2.imread('./images/dog.bmp')
print('img_color type: ', type(img_color))
print('img_color shape: ', img_color.shape) # (364, 548, 3) 세로, 가로, 채널
print('img_color dtype: ', img_color.dtype)
h, w = img_gray.shape[:2]
print("높이:", h, "너비:", w)
if len(img_gray.shape) == 3:
c = img_gray.shape[2]
print("컬러영상, 채널 수:", c)
elif len(img_gray.shape) == 2:
print("그레이스케일 영상")
3-2. NumPy로 영상 배열 생성
검은 영상, 빈 배열 채우기, 그레이 톤, 단색(BGR) 영상을 만드는 예시다.
img1 = np.zeros((240, 320, 3), dtype=np.uint8)
img2 = np.empty((240, 320), dtype=np.uint8)
img3 = np.ones((240, 320), dtype=np.uint8) * 200
img4 = np.full((240, 320, 3), (255, 0, 255), dtype=np.uint8)
img2 = cv2.cvtColor(img2, cv2.COLOR_GRAY2BGR)
img2[:, :] = (255, 102, 255)
cv2.imshow('black img', img1)
cv2.imshow('empty img', img2)
cv2.imshow('gray img', img3)
cv2.imshow('full img', img4)
cv2.imshow('dog gray', img_gray)
cv2.imshow('dog color', img_color)
OpenCV에서 컬러는 BGR 순서이므로 (255, 0, 255)는 파랑+빨강(보라 계열)이다.
3-3. waitKey와 키보드 이벤트
cv2.waitKey()는 키 입력을 기다린다. 반환값으로 ASCII 코드가 오므로, 27은 ESC, ord('i')는 'i' 키다. ESC면 루프를 빠져 나가고, 'i'/'I'면 픽셀을 반전(~img_color)한 뒤 다시 보여 주면 된다.
while True:
keyvalue = cv2.waitKey()
print(keyvalue)
if keyvalue == 27: # ESC 키
break
elif keyvalue == ord('i') or keyvalue == ord('I'):
img_color = ~img_color
cv2.imshow('dog color', img_color)
4. 도형 그리기와 마우스 이벤트
OpenCV로 사각형, 원, 텍스트를 그릴 수 있고, 마우스 콜백을 등록해 클릭·드래그 위치를 받아 선을 그리는 식으로 활용할 수 있다.
4-1. rectangle, circle, putText
cv2.rectangle(img, (x, y, w, h), color, thickness): (x, y)에서 가로 w, 세로 h 사각형.thickness=-1이면 채우기.cv2.circle(img, center, radius, color, thickness): 원 그리기.cv2.putText(img, text, (x, y), font, fontScale, color, thickness): 문자열 출력.
import cv2
import numpy as np
img = np.ones((800, 1000, 3), dtype=np.uint8) * 255
cv2.rectangle(img, (50, 200, 150, 100), (0, 255, 0), 3) # 사각형 (테두리)
cv2.rectangle(img, (300, 200, 150, 100), (255, 0, 0), -1) # 채워진 사각형
cv2.circle(img, (150, 400), 50, (255, 255, 0), 3)
cv2.putText(img, '2026', (50, 200), cv2.FONT_HERSHEY_COMPLEX, 0.7, (0, 0, 0), 2)
cv2.imshow('Mouse Event', img)
색은 BGR 순서이므로 (0, 255, 0)은 초록, (255, 0, 0)은 파랑, (255, 255, 0)은 파랑+초록(청록 계열)이다.
4-2. 마우스 콜백으로 드래그해 선 그리기
cv2.setMouseCallback(winname, on_mouse)로 창에 마우스 콜백을 붙인다. 콜백 함수는 (event, x, y, flags, param) 인자를 받고, event로 왼쪽/오른쪽/가운데 버튼 down, 이동 등을 구분할 수 있다. 드래그 중일 때는 flags가 설정되어 있으므로, 이전 좌표 (oldx, oldy)에서 현재 (x, y)까지 cv2.line()으로 선을 그리면 된다.
oldx, oldy = 0, 0
def on_mouse(event, x, y, flags, param):
global oldx, oldy
if event == cv2.EVENT_LBUTTONDOWN:
print("Left button down at ({}, {})".format(x, y))
oldx, oldy = x, y
elif event == cv2.EVENT_RBUTTONDOWN:
print("Right button down at ({}, {})".format(x, y))
elif event == cv2.EVENT_MBUTTONDOWN:
print("Middle button down at ({}, {})".format(x, y))
elif event == cv2.EVENT_MOUSEMOVE:
print("Mouse move at ({}, {})".format(x, y))
if flags:
print("드래그중")
cv2.line(img, (oldx, oldy), (x, y), (0, 0, 0), 3)
cv2.imshow('Mouse Event', img)
oldx, oldy = x, y
cv2.setMouseCallback('Mouse Event', on_mouse)
cv2.waitKey()
왼쪽 버튼을 누른 채로 움직이면 EVENT_MOUSEMOVE와 flags로 드래그를 감지하고, 매번 이전 점과 현재 점을 이어 검은색 선을 그리면 된다.
마치며
- OpenCV는
cv2로 이미지·영상을 NumPy 배열처럼 다루며,imread로 그레이스케일/컬러(BGR) 읽기,cvtColor로 BGR→RGB 변환이 기본이다. - 이미지 속성은
shape(세로, 가로, 채널),dtype(보통 uint8)로 확인하고,np.zeros/np.ones/np.full로 영상 배열을 만들 수 있다. - 키보드는
cv2.waitKey()로 받고, ESC(27)로 종료,ord('i')로 반전 등 동작을 분기할 수 있다. - 도형은
rectangle,circle,putText로 그리고, 마우스는setMouseCallback으로 이벤트를 받아 드래그 선 그리기 같은 인터랙션을 구현할 수 있다.
다음으로는 영상 연산(덧셈/뺄셈), 히스토그램, 이진화, 필터링(블러·엣지) 등을 실습해 보면 좋다.
(OpenCV - 류지 프로젝트 참고)
'AI·머신러닝 > 딥러닝·비전' 카테고리의 다른 글
| OpenCV 크로마키·ROI·이진화·기하 변환 - 투시 변환과 명함 스캐너 실습 (0) | 2026.01.05 |
|---|---|
| OpenCV 영상 입출력과 연산 - 동영상·카메라, VideoWriter, 픽셀 연산, 히스토그램·HSV (0) | 2025.12.31 |
| 전이 학습 실전 - Alien vs Predator · 콘크리트 균열 탐지, AlexNet · VGG19 활용 (0) | 2025.12.29 |
| AlexNet과 CIFAR-10 이미지 분류 - ILSVRC, 전처리, 혼동 행렬 실습 (0) | 2025.12.25 |
| CNN과 손글씨 도형 분류 - 합성곱 신경망, 학습, FastAPI·Gradio 서빙 (0) | 2025.12.23 |