※ Jupyter Notebook을 사용함
카메라와 동영상 파일 다루기
드로이드캠 영상
안드로이드 스마트폰 앱 중 DroidCam을 이용하면 스마트폰 카메라에서 촬영한 영상을 소켓 통신을 통해 보내고 받을 수 있다.
- 사용 순서 1. 플레이스토어에서 DroidCam 설치(아이폰의 경우 App Store) 2. 스마트폰에서 DroidCam 앱을 실행하고 와이파이 IP, 포트 번호, 'mpegfeed'를 사용해 VideoCapture 객체 cap을 생성(http://IP:port/mjpegfeed') 3. 와이파이 IP, 포트 번호는 스마트폰 및 와이파이 환경에 따라 다르고, 'mjpegfeed' 문자열은 앱에 따라 다를 수 있음. 아이폰의 경우 (http://IP:port/video') |
import cv2
import sys
#VideoCapture클래스 - 카메라 또는 동영상 파일로부터 정지영상 프레임을 받아올수 있다.
cap = cv2.VideoCapture('http://192.XXX.0.XXX:4747/video') # 카메라 디바이스, 동영상 파일명, 스트리밍 주소
if not cap.isOpened():
print("Camera open failed!!")
sys.exit()
w, h = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
print("frame width, height:", w, h)
fourcc = cv2.VideoWriter_fourcc(*"DIVX")
outputVideo1 = cv2.VideoWriter('./out/droid_frame.avi', fourcc, fps, (w, h))
outputVideo2 = cv2.VideoWriter('./out/droid_inverse.avi', fourcc, fps, (w, h))
while True:
ret, frame = cap.read()
if not ret:
break
inversed = ~frame
outputVideo1.write(frame)
outputVideo2.write(inversed)
cv2.imshow("frame", frame)
cv2.imshow("inversed", inversed)
if cv2.waitKey(10) == 27: #sleep 효과
break
if cap.isOpened():
cap.release()
outputVideo1.release()
outputVideo2.release()
cv2.destroyAllWindows()
### 유튜브 영상
pafy : 비디오에서 메타데이터 획득, 비디오/오디오를 다운로드 하는 패키지 youtube_dl : patfy의 backend에서 유튜브 동영상을 다운로드
설치방법 pip install pafy pip install youtube_dl
import pafy
url = 'https://www.youtube.com/watch?v=9SmQOZWNyWE&list=RD9SmQOZWNyWE&index=1'
video = pafy.new(url)
print("title:", video.title)
print("rating:", video.rating)
print("duration:", video.duration)
best = video.getbest()
# best.url : download 가능한 url
# best.resolution : video의 해상도
-->
title: BTS - "Permission to Dance" performed at the United Nations General Assembly | SDGs | Official Video
rating: None
duration: 00:03:43
best.url
-->
'https://rr5---sn-ab02a0nfpgxapox-jwws.googlevideo.com/videoplayback?expire=1641279979&ei=i53TYYimHaiRvcAPytGWiAQ&ip=112.220.17.226&id=o-ACAcwwEKI-N3p-B_CO8_0G45U7F-LrYzFKhmR5lcquQP&itag=18&source=youtube&requiressl=yes&mh=e9&mm=31%2C26&mn=sn-ab02a0nfpgxapox-jwws%2Csn-o097znz7&ms=au%2Conr&mv=m&mvi=5&pl=24&initcwndbps=472500&vprv=1&mime=video%2Fmp4&ns=d3t95BJC3u3y4sNfS22RkKUG&gir=yes&clen=19255716&ratebypass=yes&dur=223.445&lmt=1632650578912066&mt=1641258061&fvip=5&fexp=24001373%2C24007246&c=WEB&txp=5530434&n=xd87H6e0UHZEXTHb&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&sig=AOq0QJ8wRgIhALMisAkX4P-vlvm9Mn7Hw5qiZjRXxmcHtDlLgxoXSxv2AiEA4J5vC63bfOdZW_FBUbiGVFdIn5B03MkxlVV3g97kQMU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAJAWNJEqvp9p35Hu8I7s3pF7GwottMJq9KID-0_6U9mzAiAERHEIsgJ-DXXLiYkjMyHjdBRyMGF-4e7gGz_TS_LFsQ%3D%3D'
cap = cv2.VideoCapture(best.url) # 카메라 디바이스, 동영상 파일명, 스트리밍 주소
if not cap.isOpened():
print("Camera open failed!!")
sys.exit()
w, h = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
print("frame width, height:", w, h)
fourcc = cv2.VideoWriter_fourcc(*"DIVX")
outputVideo1 = cv2.VideoWriter('./out/youtube_frame.avi', fourcc, fps, (w, h))
outputVideo2 = cv2.VideoWriter('./out/youtube_edge.avi', fourcc, fps, (w, h), isColor=False)
delay = round(1000/fps)
while True:
ret, frame = cap.read()
if not ret:
break
#inversed = ~frame
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
edge = cv2.Canny(gray, 100, 200)
outputVideo1.write(frame)
outputVideo2.write(edge)
cv2.imshow("frame", frame)
cv2.imshow("edge", edge)
if cv2.waitKey(delay) == 27: #sleep 효과
break
if cap.isOpened():
cap.release()
outputVideo1.release()
outputVideo2.release()
cv2.destroyAllWindows()
-->
frame width, height: 640 360
주요 함수와 클래스
VideCapture클래스
VideoCapture::VideoCapture(const String& filename, int apiPreference = CAP_ANY);
bool VideoCapture::open(const String& filename, int apiPreference = CAP_ANY);
카메라 또는 동영상 파일로 부터 정지영상 프레임을 받아 올 수 있다.
・filename - 동영상 파일 이름
・apiPreference - 사용할 비디오 캡쳐 API백엔드
・반환값 - (VideoCapture::open()함수)열기가 성공하면 true, 실패하면false
VideoCaptureAPIs열거형 상수
・CAP_ANY - 자동선택
・CAP_V4L, CAP_V4L2 - V4L/V4L2(리눅스)
・CAP_FIREWIRE, CAP_FIREWARE, CAP_IEEE1394 - IEEE1394드라이버
등등....
VideoCapture::VideoCapture(int index, int apiPreference = CAP_ANY);
bool VideoCapture::open(int index,int apiPreference = CAP_ANY);
컴퓨터에 연결된 카메라 장치를 사용하는 클래스
・filename - 동영상 파일 이름
・apiPreference - 사용할 비디오 캡쳐 API백엔드
・반환값 - (VideoCapture::open()함수)열기가 성공하면 true, 실패하면false
VideoCapture::open() 함수에 전닿나느 정수값 index는
index = camera_id + domain_offset_id
camera_id(한대의 경우 : 0, 두대 이상의 경우 : 0보다 같거나 큰 정수를 ID로 가진다)
domain_offset_id(카메라 장치를 사용하는 방식을 표현하는 정수값 VideoCaptureAPIs열거형 상수를 지정함)
bool VideoCapture::isOpened() const;
isOpened()멤버 함수를 이용하여 열기 작업이 성공적으로 수행되었는지 확인
・반환값 - 카메라 또는 동영상 파일이 사용 가능하면 true, 그렇지 않으면 false
virtual void VideoCapture::release();
release()함수를 호출하여 사용하던 자원을 해제
VideoCapture& VideoCapture::operator >> (Mat& image);
bool VideoCapture::read(OutputArray image);
VideoCapture클래스에서 한 프레임을 받아올때 사용.
・image - 다음 비디오 프레임, 만약 더 가져올 프레임이 없다면 비어 있는 행렬로 설정됨
・반환값 - 프레임을 받아 올 수 없으면 false 반환
double VideoCapture::get(int propId) const;
현재 열려 있는 카메라 장치 또는 동영상 파일로 부터 여러가지 정보를 받아 오기 위한 함수
・propId - 속성ID, VideoCaptureProperties 열거형 중 하나를 지정합니다.
・반환값 - 지정한 속성 값, 만약 지정한 속성을 얻을 수 없으면 0을 반환합니다.
VideoCaptureProperties 열거형 상수
・CAP_PROP_POS_MSEC - 비디오 파일에서 현재 위치(밀리초 단위)
・CAP_PROP_POS_FRAMES - 현재 프레임 위치(0-기반)
・CAP_PROP_POS_AVI_PATIO - [0, 1]구간으로 표현한 동영상 프레임의 상대적 위치(0: 시작, 1:끝)
・CAP_PROP_FRAME_WIDTH - 비디오 프레임의 가로 크기
・CAP_PROP_FRAME_HEIGHT - 비디오 프레임의 세로 크기
・CAP_PROP_FPS - 초당 프레임 수
・CAP_PROP_FOURCC - fourcc코드(코덱을 표현하는 정수값)
・CAP_PROP_FRAME_COUNT - 비디오 파일의 전체 프레임 수
・CAP_PROP_BRIGHTNESS - (카메라에서 지원하는 경우) 밝기 조절
・CAP_PROP_CONTRAST - (카메라에서 지원하는 경우) 명암비 조절
・CAP_PROP_SATURATION - (카메라에서 지원하는 경우) 채도 조절
・CAP_PROP_HUE - (카메라에서 지원하는 경우) 색상 조절
・CAP_PROP_GAIN - (카메라에서 지원하는 경우) 감도 조절
・CAP_PROP_EXPSURE - (카메라에서 지원하는 경우) 노출 조절
・CAP_PROP_ZOOM - (카메라에서 지원하는 경우) 줌 조절
・CAP_PROP_FOCUS - (카메라에서 지원하는 경우) 초점 조절
bool VideCapture::set(int propId, double value);
현재 열려 있는 카메라 또는 비디오 파일 재생과 관련된 속성값을 설정할 때 사용하는 함수
・propId - 속성ID, VideoCaptureProperties 열거형 중 하나를 지정합니다.
・value - 지정할 속성 값
・반환값 - 속성 지정이 가능하면 true, 아니면 false
카메라 입력 처리하기
동영상 파일 처리하기
동영상 파일 처리하기
https://github.com/sunkyoo/opencv4cvml/blob/master/python/ch04/video.py
GitHub - sunkyoo/opencv4cvml: "OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝" (길벗, 2019) 책 소스 코드입니
"OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝" (길벗, 2019) 책 소스 코드입니다. - GitHub - sunkyoo/opencv4cvml: "OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝" (길벗, 2019) 책 소스 코드입니다.
github.com
동영상 파일 저장하기
VideoWriter::VideoWriter(sonst String& filename, int fourcc, double fps, Size frameSize, bool isColor = true);
bool VideoWriter::open(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true);
VideoWirter 객체를 생성하였으면 open()멤버 함수를 이용하여 저장할 동영상 파일을 쓰기모드로 열어야합니다.
・filename - 저장할 동영상 파일 이름
・fourcc - 동영상 압축 코덱을 표현하는 4-문자코드
・fps - 저장할 동영사의 초당 프레임수
・frameSize - 동영상 프레임의 가로 및 세로 크기
・isColor - 이 값이 true이면 컬러 동영상으로 저장하고, false이면 그레이스케일 동영상으로 저장합니다. 이 플래그는 windows운영 체제에서만 지원 합니다.
・반환값 - (VideoWriter::open() 함수)열기사 성고하면 true, 실패하면 false
static int VideoWrier::fourcc(char c1, char c2, char c3, char c4)
fourcc는 동영상 파일의 코덱, 압축 방식, 색상 색상혹은 픽셀 포맷 등을 정의 하는 정수 값으로 코덱을 표현하는 네 개의 문자를 묶어서 fourcc를 생성하는 함수
・c1, c2, c3, c4 - 코덱을 표현하는 1byte 문자 네 개
・반환값 - 정수형 4-문자코드
fourcc코드 생성 방법
・VideoWrier::fourcc('D', 'I', 'V', 'X') - DivX MPEG-4코덱
・VideoWrier::fourcc('X', 'V', 'I', 'D') - XVID MPEG-5코덱
・VideoWrier::fourcc('F', 'M', 'P', '4') - FFMPEG MPEG4 코덱
등등
VideoWriter& VideoWriter::operator << (const Mat& image);
void VideoWriter::write(InputArray image);
열려있는 동영상 파일에 새로운 프레임으 추가하기 위해서는 << 연산자 재정의 또는 write()함수를 사용
・image - 추가할 프레임
virtual void VideoWriter::release();
영상 저장이 완료되면 열려있던 파일을 닫는 함수
# 다양한 그리기 함수
### 직선 그리기
import numpy as np
# 참고 (행렬의 색인순서는 y축, 즉 행부터)
mat = np.array([[1, 2, 3],[4,5,6], [7,8,9], [10, 11, 12]])
mat[3, 0]
--> Out :
10
img = np.full((400, 400, 3), 255, np.uint8)
cv2.line(img, (50, 50), (200, 50), (0, 0, 255))
cv2.line(img, (50, 100), (200, 100), (255, 0, 255), 3)
cv2.line(img, (50, 150), (200, 150), (255, 0, 0), 10)
cv2.line(img, (250, 50), (350, 100), (0, 0, 255), 1, cv2.LINE_4)
cv2.line(img, (250, 70), (350, 120), (255, 0, 255), 1, cv2.LINE_8)
cv2.line(img, (250, 90), (350, 140), (255, 0, 0), 1, cv2.LINE_AA)
cv2.arrowedLine(img, (50, 200), (150, 200), (0, 0, 255), 1)
cv2.arrowedLine(img, (50, 250), (350, 250), (255, 0, 255), 1)
cv2.arrowedLine(img, (50, 300), (350, 300), (255, 0, 0), 1, tipLength=0.05)
cv2.drawMarker(img, (50, 350), (0, 0, 255), cv2.MARKER_CROSS)
cv2.drawMarker(img, (100, 350), (0, 0, 255), cv2.MARKER_TILTED_CROSS)
cv2.drawMarker(img, (150, 350), (0, 0, 255), cv2.MARKER_STAR)
cv2.drawMarker(img, (200, 350), (0, 0, 255), cv2.MARKER_DIAMOND)
cv2.drawMarker(img, (250, 350), (0, 0, 255), cv2.MARKER_SQUARE)
cv2.drawMarker(img, (300, 350), (0, 0, 255), cv2.MARKER_TRIANGLE_UP)
cv2.drawMarker(img, (350, 350), (0, 0, 255), cv2.MARKER_TRIANGLE_DOWN)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
-->
### 도형 그리기
img = np.full((400, 400, 3), 255, np.uint8)
cv2.rectangle(img, (50, 50), (150, 100), (0, 0, 255), 2)
cv2.rectangle(img, (50, 150), (150, 200), (0, 0, 128),-1)
cv2.circle(img, (300, 120), 30, (255, 255, 0), -1)
cv2.circle(img, (300, 120), 60, (255, 0, 0), 3)
cv2.ellipse(img, (120, 300), (60, 30), 20, 0, 270, (255, 255, 0), cv2.FILLED, cv2.LINE_AA)
cv2.ellipse(img, (120, 300), (100, 50), 20, 0, 360, (255, 0, 0), 2, cv2.LINE_AA)
pts = np.array([[250, 250], [300, 250], [300, 300], [350, 300], [350, 350], [250, 350]])
cv2.polylines(img, [pts], True, (255, 0, 255), 2)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
-->
### 문자열 출력하기
img = np.full((500, 800, 3), 255, np.uint8)
cv2.putText(img, "FONT_HERSHEY_SIMPLEX", (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255))
cv2.putText(img, "FONT_HERSHEY_PLAIN", (20, 100), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255))
cv2.putText(img, "FONT_HERSHEY_DUPLEX", (20, 150), cv2.FONT_HERSHEY_DUPLEX, 1, (0, 0, 255))
cv2.putText(img, "FONT_HERSHEY_COMPLEX", (20, 200), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0))
cv2.putText(img, "FONT_HERSHEY_TRIPLEX", (20, 250), cv2.FONT_HERSHEY_TRIPLEX, 1, (255, 0, 0))
cv2.putText(img, "FONT_HERSHEY_COMPLEX_SMALL", (20, 300), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (255, 0, 0))
cv2.putText(img, "FONT_HERSHEY_SCRIPT_SIMPLEX", (20, 350), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, 1, (255, 0, 255))
cv2.putText(img, "FONT_HERSHEY_SCRIPT_COMPLEX", (20, 400), cv2.FONT_HERSHEY_SCRIPT_COMPLEX, 1, (255, 0, 255))
cv2.putText(img, "FONT_HERSHEY_COMPLEX | FONT_ITALIC", (20, 450), cv2.FONT_HERSHEY_COMPLEX | cv2.FONT_ITALIC, 1, (255, 0, 0))
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
-->
img = np.full((200, 640, 3), 255, np.uint8)
text = "Hello, OpenCV"
fontFace = cv2.FONT_HERSHEY_TRIPLEX
fontScale = 2.0
thickness = 1
sizeText, _ = cv2.getTextSize(text, fontFace, fontScale, thickness)
# print(type(sizeText))
# sizeText[0], sizeText[1]
org = (img.shape[1] - sizeText[0])//2, (img.shape[0] + sizeText[1])//2
cv2.putText(img, text, org, fontFace, fontScale, (255, 0, 0), thickness)
cv2.rectangle(img, org, (org[0] + sizeText[0], org[1]-sizeText[1]), (0, 255, 0), 1)
#TODO : org 좌표에 동그라미 그리기
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
-->
### Workshop : 카운트 다운 영상 만들기
img = np.full((500, 500, 3), 255, np.uint8)
list = [ '1', '2', '3', '4', '5']
# 일반적인 for 문
for num in list:
text = num
fontFace = cv2.FONT_HERSHEY_COMPLEX
fontScale = 2.0
thickness = 1
sizeText, _ = cv2.getTextSize(text, fontFace, fontScale, thickness)
org = (img.shape[1] - sizeText[0])// 2, (img.shape[0] + sizeText[1])//2
cv2.putText(img, text, org, fontFace, fontScale, (255, 0, 0), thickness)
cv2.circle(img, (0, 0), 200, (0, 0, 255), 3)
cv2.circle(img, (500, 500), 200, (0, 0, 255), 3)
cv2.circle(img, (0, 500), 200, (0, 0, 255), 3)
cv2.circle(img, (500, 0), 200, (0, 0, 255), 3)
cv2.circle(img, (250, 250), 200, (0, 0, 255), 3)
cv2.imshow("img", img)
cv2.waitKey(1000)
img = np.full((500, 500, 3), 255, np.uint8)
cv2.destroyAllWindows()
--> 5 4 3 2 1 로 카운트 다운한다.
주요 함수와 클래스
다양한 그리기 함수
void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
영상위에 직선을 그리는 함수
・img - 입출력 영상
・pt1 - 시작점
・pt2 - 끝점
・color - 선 색상(또는 밝기)
・thickness - 선 두께
・lineType - 선 타입, LINE_4, LNNE_8, LINE_AA 중 하나를 지정합니다.
・shift - 그리기 좌표 값의 축소 비율(오른쪽 비트 시프트(>>)연산)
LineTypes 열거형 상수
・FILLED(-1) - 내부를 채움(직선 그리기 함수에는 사용 불가)
・LINE_4(4) - 4방향 연결
・LINE_8(8) - 8방향 연결
・LINE_AA(18) - 안티에일리어싱(anti-aliasing)
void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0, double tipLength=0.1);
영상위에 화살표 형태의 직선을 그리는 함수
・ img - 입출력 영상
・ pt1 - 시작점
・ pt2 - 끝점
・ color - 선 색상(또는 밝기)
・ thickness - 선 두께
・ lineType - 선 타입, LINE_4, LNNE_8, LINE_AA 중 하나를 지정합니다.
・ shift - 그리기 좌표 값의 축소 비율(오른쪽 비트 시프트(>>)연산)
・ tipLength - 전체 직선 길이에 대한 화살표 길이의 비율
void drawMarker(InputOutputArray img, Point pisition, const Scalar& color, int markerType = MARKER_CROSS, int markerSize=20, int thickness = 1, int line_type = 8);
직선 그리기 함수를 이용하여 다양한 모양의 마커를 그립니다.
・ img - 입출력 영상
・ pisition - 마커 출력 위치
・ color - 선 색상
・ markerType - 마커 종류. markerType 열거형 상수중 하나를 지정합니다.
・ markerSize - 마커 크기
・ thickness - 선 두께
・ lineType - 선 타입, LINE_4, LNNE_8, LINE_AA 중 하나를 지정합니다.
markerType 열거형 상수
・MARKER_CROSS - 십자가 모양(+ 모양)
・MARKER_TILTED_CROSS - 45도회전된 십자가 모양(ⅹ 모양)
・MARKER_STAR - MARKER_CROSS 모양과 MARKER_TILTED_CROSS모양이 합쳐진 형태
・MARKER_DIAMOND - 마름모 모양(◇ 모양)
・MARKER_SQUARE - 정사각형 모양(□ 모양)
・MARKER_TRIANGLE_UP - 위로 뾰족한 삼각형(△ 모양)
・MARKER_TRIANGLE_DOWN - 아래로 뾰족한 삼각형(▽ 모양)
void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
void rectangle(InputOutputArray img, Rect rec, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
영상에 사각형을 그리는 함수
・ img - 입출력 영상
・ pt1 - 사각형 꼭지점 좌표, Point 객체
・ pt2 - pt1과 대각 방향에 있는 사각형 꼭지점 좌표, Point 객체
・ rec - 사각형 위치 정보, Rect객체
・ color - 사각형 색상(또는 밝기)
・ thickness - 사각형 외곽선 두께, 이 값이 음수(-1 또는 FILLED)이면 내부를 채웁니다.
・ lineType - 선 타입
・ shift - 그리기 좌표 값의 축소 비율(오른쪽 비트 시브트(>>) 연산)
void circle(InputOutputArray img, Point center, int radius, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
영상에 원을 그리는 함수
・ img - 입출력 영상
・ center - 원의 중심
・ radius - 원의 반지름
・ color - 원 색상
・ thickness - 원 외곽선 두께, 이 값이 음수(-1 또는 FILLED)이면 내부를 채웁니다.
・ lineType - 선 타입
・ shift - 그리기 좌표 값의 축소 비율(오른쪽 비트 시브트(>>) 연산)
vodi ellipse(InputOutputArray img, Point center, Size axes, double angle, double starAngle, double endAngle, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
영상에 타원을 그리는 함수
・ img - 입출력 영상
・ center - 타원의 중심
・ axes - 타원의 반지름, Size(x축_반지름, y축_반지름)
・ angle - 타원 회전 각도(x축 기준, 시계 방향)
・ starAngle - 타원 호의 시작 각도(x축 기준, 시계 방향)
・ endAngle - 타원 호의 끝 각도(x축 기준, 시계 방향)
・ color - 타원 색상
・ thickness - 타원 외곽선 두께, 이 값이 음수(-1 또는 FILLED)이면 내부를 채웁니다.
・ lineType - 선 타입
・ shift - 그리기 좌표 값의 축소 비율(오른쪽 비트 시브트(>>) 연산)
void polylines(InputOutputArray img, InputArrayOfArrays pts, bool isClosed, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);
영상에 다각형을 그리는 함수
・ img - 입출력 영상
・ pts - 다각형 외곽 점들의 배열, 주로 vector<Point>타입
・ isClosed - 다각형이 닫혀 있는지를 나타내는 플래그, 이 값이 true이면 다각형의 마지막 꼭지점과 첫 번쨰 꼭지점을 잇는 직선을 추가로 그립니다.
・ color - 선 색상
・ thickness - 선 두께, 이 값이 음수(-1 또는 FILLED)이면 내부를 채웁니다.
・ lineType - 선 타입
・ shift - 그리기 좌표 값의 축소 비율(오른쪽 비트 시브트(>>) 연산)
문자열 출력하기
void putText(InputOutputArray img, const String& text, Point org, int fontFace, double fontScale, Scalar color, int thickness = 1, int lineType = LINE_8, bool bottomLeftOrigin = false);
영상 위에 정해진 폰트로 문자열을 출력하는 함수
・ img - 입출력 영상
・ text - 출력할 문자열
・ org - 영상에서 문자열을 출력할 위치의 좌측 하단 좌표
・ fontFace - 폰트 종류. cv::HersheyFonts에서 선택
・ fontScale - 폰트 크기 확대/ 축소 비율
・ color - 문자열 색상
・ thickness - 문자열을 그릴 때 사용할 선 두께
・ lineType - 선 타입, LINE_4, LNNE_8, LINE_AA 중 하나를 지정합니다.
・ bottomLeftOrigin - 이 값이 true이면 영상의 좌측 하단을 원점으로 간주합니다.false이면 좌측 상단이 원점입니다.
HersheyFonts 열거형 상수
・ FONT_HERSHEY_SIMPLEX - 일반 크기의 산세리프 폰트
・ FONT_HERSHEY_PLAIN - 작은 크기의 산세리프 폰트
・ FONT_HERSHEY_DUPLEX - 일반 크기의 산세리프 폰트(FONT_HERSHEY_SIMPLEX보다 복잡한 형태)
・ FONT_HERSHEY_COMPLEX - 일반 그기의 세리프 폰트
・ FONT_HERSHEY_TRIPLEX - 일반 그기의 세리프 폰트(FONT_HERSHEY_COMPLEX보다 복잡한 형태)
・ FONT_HERSHEY_COMPLEX_SMALL - FONT_HERSHEY_COMPLEX보다 작은 폰트
・ FONT_HERSHEY_SCRIPT_SIMPLEX - 필기체 스타일의 폰트
・ FONT_HERSHEY_SCRIPT_COMPLEX - 필기체 스타일의 폰트(FONT_HERSHEY_SCRIPT_SIMPLEX 보다 복잡한 형태)
・ FONT_ITALIC - 이탤릭체를 위한플래그
Size getTextSize(const String& text, int fontFace, double fontScale, int thickness, int* baseLine);
문자열 출력을 위해 필요한 사각형 영역 크기를 가늠 할수 있는 함수
・ text - 출력할 문자열
・ fontFace - 폰트 종류
・ fontScale - 폰트 크기 확대/ 축소 비율
・ thickness - 문자열을 그릴 때 사용할 선 두께
・ baseLine - (출력)가장 하단의 텍스트 위치를 기준으로 하는 기준선(baseline)의 y 좌표, 필요 없으면 0 지정
・ 반환값 - 지정한 문자열 출력 시 차지하는 사각형 크기
# 이벤트 처리
### Keyboard Event
img = cv2.imread('./data/lenna.bmp')
if img is None:
print('Image load failed!')
sys.exit()
cv2.imshow('img', img)
while True:
keycode = cv2.waitKey()
if keycode == ord('i') or keycode == ord("I"): #'i',"I"를 입력했을 경우
img = ~img
cv2.imshow("img", img)
elif keycode == ord('q') or keycode == ord("Q"): #'q',"Q"를 입력했을 경우
break
cv2.destroyAllWindows()
### Workshop : 키보드 이벤트 처리
img = np.full((512, 512, 3), 255, np.uint8)
x, y = img.shape[0]//2, img.shape[1]//2
width , height = img.shape[1], img.shape[0]
R = 50
direction = 0
while True:
keycode = cv2.waitKeyEx(50)# 키보드에서 입력키받음
if keycode == 0x1B: #ESC키
break;
elif key==0x270000: # 방향키 방향 전환 0x270000==right
direction=0
elif key==0x280000: # 방향키 방향 전환 0x280000==down
direction=1
elif key==0x250000: # 방향키 방향 전환 0x250000==left
direction=2
elif key==0x260000: # 방향키 방향 전환 0x260000==up
direction = 3
if direction == 0:
x += 10
elif direction == 1:
y += 10
elif direction == 2:
x -= 10
elif direction == 3:
y -=10
# 경계처리
if x < R:
x = R
direction = 0
if x > width - R:
x = width -R
direction = 2
if y < R:
y = R
direction = 1
if y > height - R:
y = height - R
direction = 3
cv2.circle(img, (x, y), R, (0, 0, 255), -1)
cv2.imshow('img', img)
img = np.full((512, 512, 3), 255, np.uint8)
cv2.destroyAllWindows()
### Mouse Event
def on_mouse(event, x, y, flags, param):
global old_x, old_y
if event == cv2.EVENT_LBUTTONDOWN:
old_x, old_y = x, y
elif event == cv2.EVENT_LBUTTONUP:
pass
elif event == cv2.EVENT_MOUSEMOVE:
if flags & cv2.EVENT_FLAG_LBUTTON:
cv2.line(img, (old_x, old_y), (x, y), (0, 255, 255), 2)
cv2.imshow('img', img)
old_x, old_y = x, y
img = cv2.imread('./data/lenna.bmp')
if img is None:
print("Image load failed!")
sys.exit()
cv2.namedWindow("img")
cv2.setMouseCallback("img", on_mouse)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
### Workshop : 마우스 이벤트 처리
# 왼쪽 클릭 파란 동그라미 cv2.EVENT_LBUTTONDOWN
# 쉬프트 같이 왼쪽클릭 파란 사각형 cv2.EVENT_FLAGSHIFTKEY
# 오른쪽 클릭 빨간 동그라미 cv2.EVENT_RBUTTONDOWN
# 왼쪽 버튼 더블클릭 모두 삭제 cv2.EVENT_LBUTTONDBLCLK
def on_mouse(event, x, y, flags, param):
global img
if event == cv2.EVENT_LBUTTONDOWN:
if flags & cv2.EVENT_FLAG_SHIFTKEY:
cv2.rectangle(img,(x-5, y-5), (x+5, y+5),(255,0,0))
else :
cv2.circle(img,(x, y), 5,(255,0,0), 3)
elif event == cv2.EVENT_RBUTTONDOWN:
cv2.circle(img,(x, y), 5,(0,0,255), 2)
elif event == cv2.EVENT_LBUTTONDBLCLK:
param[0] = np.full((512, 512, 3), 255, np.uint8)
cv2.imshow("img", param[0])
img = np.full((512, 512, 3), 255, np.uint8)
cv2.imshow("img", img)
cv2.setMouseCallback("img", on_mouse, [img])
cv2.waitKey()
cv2.destroyAllWindows()
### Trackbar
def saturated(value):
if value > 255:
value = 255
elif value < 0:
value = 0
return value
def on_level_change(pos):
img[:] = saturated(pos*16)
cv2.imshow("img", img)
img = np.full((512, 512, 3), 255, np.uint8)
cv2.imshow("img", img)
cv2.createTrackbar('level', 'img', 0, 16, on_level_change)
cv2.waitKey()
cv2.destroyAllWindows()
### Workshop : 트랙바 이벤트 처리
def onChange(pos):
global img
R = cv2.getTrackbarPos('R', 'img')
G = cv2.getTrackbarPos('G', 'img')
B = cv2.getTrackbarPos('B', 'img')
img[:] = (B, G, R)
cv2.imshow('img', img)
img = np.full((512, 512, 3), 255, np.uint8)
cv2.imshow("img", img)
cv2.createTrackbar('R', 'img', 0, 255, onChange)
cv2.createTrackbar('G', 'img', 0, 255, onChange)
cv2.createTrackbar('B', 'img', 0, 255, onChange)
cv2.waitKey()
cv2.destroyAllWindows()
주요 함수와 클래스
이벤트 처리
키보드 이벤트 처리
int waitKey(int delay = 0);
프로그램상에서 키 입력을 확인하기 위해 사용한 함수. delay에 해당하는 밀리초 시간 동안 키입력을 기다리다가키 입력이 있으면 아스키 코드값을 반환합니다.
・ delay - 키 입력을 기다릴 시간(밀리초 단위). delay ≤ 0 이면 무한히 기다립니다.
・ 반환값 - 눌러진 키 값. 지정한 시간 동안 키가 눌리지 않았으면 -1을 반환합니다.
특수키 waitKey()반환값 특수키 waitKey()반환값 Insert 0x2d0000 F1 0x700000 Delete 0x2e0000 F2 0x710000 Home 0x240000 F3 0x720000 End 0x230000 F4 0x730000 Page Up 0x210000 F5 0x740000 Page Down 0x220000 F6 0x750000 ← 0x250000 F7 0x760000 ↑ 0x260000 F8 0x770000 → 0x270000 F9 0x780000 ↓ 0x280000 F10 0x790000 F11 0x7a0000 F12 0x7b0000
마우스 이벤트 처리
void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);
특정 창에 마우스 콜백 함수를 등록할 때에 사용하는 함수. 창에서 마우스 클릭에 반응하거나 마우스를 드래그 하여 영상에 그림을 그리는 등의 동작을 수행 할 수 있습니다.
・ winname - 마우스 이벤트 처리를 할 창의 이름
・ onMouse - 마우스 이벤트 처리를 위한 콜백 함수 이름
・ userdata - 콜백 함수에 전달할 사용자 데이터의 포인터
MouseEventTypes 열거형 상수
・ EVENT_MOUSEMOVE(값 : 0) - 마우스가 창 위에서 움직이는 경우
・ EVENT_LBUTTONDOWN(값 : 1) - 마우스 왼쪽 버튼을 누른 경우
・ EVENT_RBUTTONDOWN(값 : 2) - 마우스 오른쪽 버튼을 누른 경우
・ EVENT_MBUTTONDOWN(값 : 3) - 마우스 가운데 버튼을 누른 경우
・ EVENT_LBUTTONUP(값 : 4) - 마우스 왼쪽 버튼을 떼는 경우
・ EVENT_RBUTTONUP(값 : 5) - 마우스 오른쪽 버튼을 떼는 경우
・ EVENT_MBUTTONUP(값 : 6) - 마우스 가운데 버튼을 떼는 경우
・ EVENT_LBUTTONDBLCLK(값 : 7) - 마우스 왼쪽 버튼을 더블클릭하는 경우
・ EVENT_RBUTTONDBLCLK(값 : 8) - 마우스 오른쪽 버튼을 더블클릭하는 경우
・ EVENT_MBUTTONDBLCLK(값 : 9) - 마우스 가운데 버튼을 더블클릭하는 경우
・ EVENT_MOUSEWHEEL(값 : 10) - 마우스 휠을 앞뒤로 돌리는 경우
・ EVENT_MOUSEHWHEEL(값 : 11) - 마우스 휠을 좌우로 움직이는 경우
MouseEventFlags 열거형 상수
・ EVENT_FLAG_LBUTTON(값 : 1) - 마우스 왼쪽 버튼이 눌려 있음
・ EVENT_FLAG_RBUTTON(값 : 2) - 마우스 오른쪽버튼이 눌려 있음
・ EVENT_FLAG_MBUTTON(값 : 4) - 마우스 가운데버튼이 눌려 있음
・ EVENT_FLAG_CTRLKEY(값 : 8) - Ctrl키가 눌려 있음
・ EVENT_FLAG_SHIFTKEY(값 : 16) - Shift키가 눌려 있음
・ EVENT_FLAG_ALTKEY(값 : 32) - Alt 키가 눌려 있음
트랙바 이벤트 처리
int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, TrackbarCallback onChange = 0, void* userdata = 0);
트랙바는 슬라이더 컨트롤이라고도 부르며, 영상 출력 창에 부착되어 프로그램 동작 중에 지정된 범위 안의 값을 선택할 수 있다. 트랙바를 생성하려면 createTrackbar()함수를 사용
・ trackbarname - 트랙바 이름
・ winname - 트랙바를 생성할 창 이름
・ value - 트랙바 위치를 받을 정수형 변수의 주소
・ count - 트랙바 최대 위치
・ onChange - 트랙바 위치가 변경될 때마다 호출되게 만들 콜백 함수 이름(함수의 포인터)
・ userdata - 트랙바 콜백 함수에 전달할 사용자 데이터의 표인터
・ 반환값 - 정상 동작하면 1을, 실패하면 0을 반환합니다.
int getTrackbarPos(const String & trackbarname, const String& winname);
트랙바를 생성한후 트랙바의 현재 위치를 알수있는 함수
・ trackbarname - 트랙바 이름
・ winname - 트랙바가 부착되어 있는 창 이름
・ 반환값 - 지정한 트랙바 현재 위치
void setTrackbarPos(const String & trackbarname, const String& winname, int pos);
프로그램 동작중 트랙바 위치를 강제로 특정 위치로 옮기고 싶을 경우 사용하는 함수
・ trackbarname - 트랙바 이름
・ winname - 트랙바가 부착되어 있는 창 이름
・ pos - 트랙바를 이동할 위치
데이터 파일 입출력
FileStorage 클래스
virtual bool FileStorage::open(const STring& filename, int flags, const String& encoding = String())
데이터 파일 입출력 기능을 캡슐화 하여 지원하는 클래스
・ filename - 파일 이름
・ flags - 파일 열기 모드
・ encoding - (XML)파일 인코딩 방식
・ 반환값 - 정상적으로 파일을 열면 true, 실패하면 false를 반환합니다.
FileStorage::mode 열거형 상수
FileStorage::READ - 읽기 모드
FileStorage::WRITE - 쓰기 모드(새로 생성)
FileStorage::APPEND - 추가로 쓰기 모드
FileStorage::MEMORY - 논리합 연사자(¦)를 이용하여 FileStorage::READ 또는 FileStorage::WRITE 상수와 함께 사용될 경우, 실제 파일 입출력 대신 메모리 버퍼를 이용한 입출력을 수행합니다.
virtual bool FileStorage::isOpened() const;
데이터 파일 열기를 시도한 후에는 해당 파일이 정상적으로 열렸는지 확인하는 함수
・ 반환값 - 파일이 정상적으로 열려있으면 true, 그렇지 않으면 false를 반환
virtual void FileStorage::release();
사용하고 있던 파일을 닫고 메모리 버퍼를 해제
데이터 파일 저장하기
template<typename _Tp>
static FileStorage& operator << (FileStorage& fs, const _Tp& value);
static FileStorage& operator << (FileStorage& fs, const String& str);
static FileStorage& operator << (FileStorage& fs, const char* str);
FileStorage 클래스 객체에 데이터를 저장할 때 사용하는 << 연산자 재정의 함수
・ fs - FileStorage객체
・ value - 저장할 데이터(백터, 클래스 등)
・ str - 문자열(이름 또는 값)
・ 반환값 - FileStorage 객체의 참조
데이터 파일 불러오기
FileNode FileStorage::operator[](const char* nodename) const;
특정이름으로 저장되어 있는 FileNode 객체에 접근하려면 연산자 재정의 함수 사용
・ fs - 노드 이름
・ 반환값 - FileNode 객체
template<typename _Tp>
static void operator >> (const FileNode& n, _Tp& value);
template<typename _Tp>
static void operator >> (const FileNode& n, std::vector<_Tp>& vec);
FileNode 객체를 얻어 온 후에는 FileNode 클래스의 >> 연산자 재정의 함수를 이용하여 노드엥 저장된 데이 값을 받아 올수 있다.
・ n - FileNode 객체
・ value 받아올 데이터 형식에 맞는 변수 이름
・ vec - STL vector 형식으로 지정된 데이터를 블러올 때 사용합니다.
반응형
'IT > Python' 카테고리의 다른 글
【OpenCV 4】Day4_유용한 기능 (0) | 2022.02.13 |
---|---|
【OpenCV 4】Day3_유용한 기능 (0) | 2022.01.26 |
【OpenCV 4】Day1_기초 사용법 (0) | 2022.01.21 |
【딥러닝 시작하기】03 다양한 신경망 (0) | 2021.12.17 |
【딥러닝 시작하기】02 텐서플로우와 신경망 (0) | 2021.12.17 |