Data_Analysis_Track_33/Python
Python_opencv_01(opencv 개요)
lsc99
2023. 10. 5. 17:27
Image란?
Image는 width X height X channel 의 pixels로 이루어진 matrix
- width: 너비로 이미지의 가로 길이를 의미한다.
- height: 높이로 이미지의 세로 길이를 의미한다.
- pixel: image가 가지고 있는 값으로 width X height 개수만큼 존재한다. image를 표현하는 bit방식에 따라 값의 범위가 달라진다.
- 일반적인 Image는 unsigned integer 8bit로 표현
- 0 ~ 255 로 표현 - bit수가 높아질 수록 표현할 수 있는 색의 범위가 증가한다.
Open CV 개요
- https://opencv.org/
- Open Source Computer Vision Library로 실시간 computer vision을 목적으로 개발됨.
- Intel에서 개발하다가 open source화 됨.
- Cross Platform으로 Windows, Mac, Linux, OS에 상관없이 동작 가능
- C/C++로 개발 되었으나 Python, JAVA, MATLAB의 개발 환경도 지원한다.
- 실시간에 초점을 맞추고 나온 library이기 때문에 mobile device나 로봇 등에 recognition module로 붙여 영상처리에 활용된다.
- OpenCV 설치
- !pip install opencv-contrib-python
이미지 읽기
- imread(filename [, flag]) : ndarray
- 이미지를 읽는다.
- filename: 읽어들일 이미지 파일경로
- flag: 읽기 모드
- cv2.IMREAD_XXXXX 상수를 이용한다.
- IMREAD_COLOR가 기본(BGR 모드)
- matplotlib에서 출력시 rgb 모드로 변환해야 한다.
- 읽은 이미지를 ndarray(numpy 배열) 로 반환한다.
cv2 import, 이미지 파일 경로로 읽어들이기
import cv2
img_path = r"images/penguin.jpg"
img = cv2.imread(img_path)
print(type(img))
print(img.shape) # 결과값 (222, 296, 3) -> (height, width, channel)을 의미
print(img.dtype)
img
이미지 출력하기
# 출력
cv2.imshow('frame', img)
cv2.waitKey()
cv2.destroyAllWindows()
img2 = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
print(img2.shape)
# (height, width) -> channel축이 없음 -> gray scale(회색조-흑백)
cv2.imshow('frame', img2)
cv2.waitKey()
cv2.destroyAllwindows
matplotlib 으로 출력
- jupyter notebook 내에 출력이 가능
- cv2.waitKey(밀리초): int
- 지정한 밀리초(1/1000 초)동안 keyboard 입력을 기다린다.
- 입력된 key 코드를 반환하며 지정된 시간동안 keyboard입력을 못받은 경우 -1을 반환한다.
- argument로 0을 입력하면 keyboard 입력을 받을 때 까지 무한 대기한다.
- https://www.ascii-code.com/
import matplotlib.pyplot as plt
# graysacle
plt.imshow(img2, cmap = 'gray')
plt.axis('off') # 경계선(spine)을 제거
plt.show()
# matplot lib -> RGB
plt.imshow(img[:, :, ::-1]) # 3차원 배열 -> 컬러이미지로 출력(height, width, channel)
plt.show()# matplot lib -> RGB
색공간 변환
- cv2.cvtColor(src, code)
- image 의 color space를 변환한다.
- src: 변환시킬 이미지 (ndarray)
- code
- 변환시킬 색공간 타입 지정
- cv2.COLOR_XXX2YYY 형태의 상수 지정(XXX를YYY로 변환)
- cv2.COLOR_BGR2GRAY / cv2.COLOR_GRAY2BGR (BGR <-> GRAY)
- cv2.COLOR_BGR2RGB / cv2.COLOR_RGB2BGR (BGR <-> RGB)
- cv2.COLOR_BGR2HSV / cv2.COLOR_HSV2BGR (BGR <-> HSV)
HSV 색공간
- Hue: 색상, 색의 종류
- Saturation: 채도. 색의 선명도
- Value : 명도. 밝기
- color를 gray로 변환하면 색정보를 손실하는 단점이 있지만 저장용량을 줄이고 처리속도를 향상시킬 수 있다.
# img # BGR -> RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# img # BGR -> GRAY
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# img # BGR -> HSV
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# img # RGB -> HSV
img_hsv2 = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
print(img[0,0])
print(img_rgb[0,0])
print(img_gray[0,0])
print(img_hsv[0,0])
print(img_hsv2[0,0])
cv2에서 이미지 출력
- cv2.imshow(winname, mat)
- 창을 띄워 이미지를 출력한다.
- winname: 창 이름
- 창이름이 같으면 같은 창에 띄운다.
- mat: 출력할 이미지(ndarray)
- dtype이 uint8이어야 정상 출력된다. (float일 경우 255를 곱해서 출력한다.) - cv2.imwrite(filename, img): bool
- 이미지 파일로 저장
- filename: 저장할 파일경로
- img: 저장할 이미지(ndarray)
이미지 불러오기
import cv2
img1 = cv2.imread(r"images/penguin.jpg")
img2 = cv2.imread(r"images/Lenna.png")
img3 = cv2.imread(r"images/window.jpg")
출력
# 출력
cv2.imshow('frame1', img1)
cv2.waitKey()
cv2.imshow('frame2', img2)
cv2.waitKey()
cv2.imshow('frame3', img3)
cv2.waitKey()
cv2.destroyAllWindows()
waitKey()는 int형으로 입력받는다
cv2.imshow('frame', img3)
v = cv2.waitKey()
print(v)
cv2.destroyAllWindows()
지금까지 이미지가 뜨고 아무 키나 눌렀을 때 창이 닫혔는데 이를 q를 눌렀을 때만 창이 닫히도록 한다.
# 특정 키를 입력했을 때 종료
cv2.imshow('frame', img3)
while True:
# if cv2.waitKey() == 27: # ESC
if cv2.waitKey() == ord('q'): # 표준함수: 문자를 유니코드값으로 변환
break
cv2.destroyAllWindows()
이미지파일을 저장할 디렉토리 생성 후, 디렉토리에 이미지 파일 저장하기
cv2.imwrite('경로/파일명', 저장할 이미지)
# 디렉토리 생성
import os
os.makedirs('output', exist_ok = True)
cv2.imwrite('output/img1.jpg', img1)
cv2.imwrite('output/img2.jpg', img2)
cv2.imwrite('output/img3.jpg', img3)
동영상 처리
동영상 읽기
- VideoCapture 클래스사용
- 객체 생성
- VideoCapture('동영상파일 경로'): 동영상파일
- VideoCapture(웹캠 ID): 웹캠 - VideoCapture의 주요 메소드
- isOpened(): bool
- 입력 대상과 연결되었는지 여부반환
- read(): (bool, img)
- Frame 이미지로 읽기
- 반환값
- bool: 읽었는지 여부
- img: 읽은 이미지(ndarray)
- release()
- 카메라/동영상과 연결 종료
카메라를 키고 아래 코드 실행
import cv2
# VideoCapture 객체 생성 -> 대상과 연결.
cap = cv2.VideoCapture(0) # int : 웹캠(0부터 1씩 증가), str : 동영상파일.
print('연결성공여부:', cap.isOpened())
# 반복문에서 한 프레임씩 읽어서 처리한다.
while cap.isOpened():
# 한 프레임 읽기
suss, img = cap.read() # (성공여부 : bool, frame : ndarray)
if not suss:
print('읽지 못했습니다.')
break
###########
# 이 부분에 처리 코드가 들어간다.
###########
# 좌우반전. cv2.flip(대상이미지, flag) - flag : 양수 - 수평, 0 - 수직, 음수 - 수평/수직 둘다
img = cv2.flip(img,1)
# 출력
cv2.imshow('frame', img)
# ESC를 입력하면 종료하도록 처리. (입력을 1/1000초 만 대기)
if cv2.waitKey(1) == 27:
break
# 연결 닫기
cap.release()
# 영상출력 창 닫기
cv2.destroyAllWindows()
동영상 재생
import cv2
cap = cv2.VideoCapture('images/wave.mp4') # str : 동영상파일 경로
print(cap.isOpened())
# 동영상의 FPS(Frame Per Second)를 조회 -> 1초에 몇 frame(영상)씩 보여주는지.
# cap.get(flag) : 연결된 동영상(webcam, 파알) 에 대한 정보를 조회
fps = cap.get(cv2.CAP_PROP_FPS)
print("FPS:", fps)
delay = int(1000/fps) # 한장 출력 시간. waitKey()에 들어가는 상수는 밀리초 단위이기에 1000
print('FPS:', fps, "delay:", delay)
while cap.isOpened():
succ, img = cap.read() # 한 frame 읽기
if not succ:
print('읽기 실패')
break
cv2.imshow('wave.mp4', img)
if cv2.waitKey(delay) == 27:
break
cap.release()
cv2.destroyAllWindows()
동영상 저장
- capture(read)한 이미지 프레임을 연속적으로 저장하면 동영상 저장이 된다.
- VideoWriter 객체를 이용해 저장
- VideoWriter(filename, codec, fps, size)
- filename: 저장경로
- codec
- VideoWriter_fourcc 이용
- fps
- FPS (Frame Per Second) - 초당 몇 프레임인지 지정
- size
- 저장할 frame 크기로 원본 동영상이나 웹캠의 width, height 순서로 넣는다. - VideoWriter().write(img)
- Frame 저장
실행후 종료까지의 영상을 저장하는 코드
# 웹캠입력 -> 저장
import cv2
cap = cv2.VideoCapture(0)
fps = cap.get(cv2.CAP_PROP_FPS)
# 한 frame을 캡쳐해서 size를 조회
_, img = cap.read()
h, w = img.shape[:2]
# print(img.shape) # height, width, channel
# print(fps)
# 코덱 생성
codec = cv2.VideoWriter_fourcc(*"MJPG")
writer = cv2.VideoWriter('output/webcam_output.avi', codec, fps, (w, h))
while cap.isOpened():
succ, img = cap.read()
if not succ:
print('읽기 실패')
break
img = cv2.flip(img, 1)
writer.write(img) # frame단위로 출력
cv2.imshow('frame', img)
if cv2.waitKey(1) == 27:
break
cap.release()
writer.release()
cv2.destroyAllWindows()