목표
- Open CV의 기본데이터 타입 Mat에 대해 알아보기
- 영상, 비디오 읽고 출력하는 방법을 알아보기
1. Mat이란?
Open CV의 기본 데이터 타입으로 Matrix(행렬)의 약어이다.
영상은 픽셀들의 집합으로 구성되어있고, 각의 픽셀들은 2차원 좌표로 그 위치를 표현가능하다.
즉, 영상은 2차원배열로 생각할 수 있다는 의미이다.
Mat 선언방법에는
- Mat(int rows, int cols, int type) 행,열 개수와 각각의 픽셀타입 설정
- Mat(Size size, int type) size 함수로 메트릭스 크기 설정함
- Mat(const Mat & m) 이미 선언되어있는 메트릭스가 있는 경우, 그 메트릭스을 받아오는 방법. m과 크기가 같으면서 메트릭스를 복사해온다.
- Mat(Size size, int type, const Scalar & s) 각각의 픽셀의 특정한 값을 설정하는 방법
Pixel type (고정 픽셀 유형)
Mat의 element가 특정 형식의 데이터인지를 지정한다.
- CV_8U: 8-bit unsigned integer: uchar ( 0~255 ) - CV_8S: 8-bit signed integer: schar ( -128~127 ) - CV_16U: 16-bit unsigned integer: ushort ( 0~65535 ) - CV_16S: 16-bit signed integer: short ( -32768~32767 ) - CV_32S: 32-bit signed integer: int ( -2147483648~2147483647 ) - CV_32F: 32-bit floating-point number: float ( -FLT_MAX~FLT_MAX, INF, NAN ) - CV_64F: 64-bit floating-point number: double (-DBL_MAX~ DBL_MAX, INF, NAN ) Multi-channel array: CV_8UC3, CV_8U(3), CV_64FC4, CV_64FC(4) |
CV_8UC1에서
- CV : 컴퓨터비전의 약자
- 8 : 비트단위, 하나의 픽셀을 표현하기 위해서 8bits를 활용하겠다는 의미.
- U : unsigned의 약자 (S : signed, F : floating)
- C1 : channel-1, 즉 채널 1개를 의미
openCV에서 mat을 단순히 영상을 표현하는데만 사용하는 것이 아니라. 일반적인 행렬 영상에도 사용하거나
전처리과정이나 에지검출 과정 때 같이, 경우에 따라 위와 같은 다양한 픽셀 타입을 선언할 수 있다.
Example
Mat mtx(3, 3, CV_32F);
// make a 3x3 floating-point matrix
// 세로3가로3, 픽셀 float타입
Mat cmtx(10, 1, CV_64FC2);
// make a 10x1 2-channel floating-point matrix
// (10-element complex vector)
//밑의 두 선언은 같은 매트릭스로 Size함수 사용하고 안하고의 차이.
Mat img(1080, 1920, CV_8UC3); // 세로, 가로 순으로 선언
// make a 3-channel (color) image of 1920 columns and 1080 rows.
Mat img(Size(1920, 1080), CV_8UC3); //Size함수를 사용하는 경우엔 가로, 세로 순으로 선언함
// make a 3-channel (color) image of 1920 columns and 1080 rows.
// 가장 기본적인 openCV 활용코드
#include "cv.hpp" // openCV활용하기 위해 추가해주는 헤더
#include <iostream> // c++ 활용하기 위해 사용하는 헤더
using namespace cv; // openCV활용하기 위해 nampspace 추가
using namespace std; // c++ 이하생략...
int main()
{
int w = 150, h = 100; // 가로, 세로
Mat image(h, w, CV_8UC1, Scalar(255)); // 이미지. 1-channel이기 때문에 scalar값 하나만 설정함
cout << "Size: " << image.size().height << "," << image.size().width << endl;
imshow("image", image); // 영상출력. image라는 이름을 가진 윈도우에 해당 메트릭스 결과 출력.
waitKey(0);
return 0;
}
Scalar(255,0,0) 3-channel인 경우 선언방법. openCV의 경우 B,G,R순서로 선언됨.
2. 영상을 읽어들이는 방법
- Mat imread(const string& filename, int flags=1)
imread 함수를 사용해서 영상을 읽는다.
파라미터1 : 읽어들이는 영상의 파일이름
파라미터2 : 이 영상을 컬러or그레이스케일로 받아들일 것인지를 결정함)
Flag value as 1:read image as color image
Flag value as 0:read image as gray scale image
int main() {
Mat gray_image, color_image;
// 0 on the 2nd parameter means read img in grayscale
gray_image = imread("lena.png", 0);
// blank 2nd parameter means 1, which means read img in colors
color_image = imread("lena.png");
imshow("gray image", gray_image);
imshow("color image", color_image);
waitKey(0);
return 0;
}
Example
- file로부터 비디오 읽어옴
int main() {
Mat frame;
VideoCapture cap; // 비디오를 읽기 위해 활용하는 클래스로 openCV에서 제공함
// check if file exists. if none program ends
// 특정한 파일(동영상)로부터 동영상을 읽어옴
if (cap.open("background.mp4") == 0) { // 해당 파일이 존재하지 않을 때
cout << "no such file!" << endl;
waitKey(0);
}
while (1) {
cap >> frame; // 다수의 영상의 집합이 모여있는 cap에서 하나의 영상, 프레임이 matrix에 이동된다.
if (frame.empty()) { // 비어있는 경우 -> 모든 영상을 다 참조했다는 의미
cout << "end of video" << endl;
break; // 무한루프 빠져나옴
}
imshow("video", frame); // 각각의 프레임을 출력함
waitKey(33); // 동영상을 구성하는 영상 사이의 간격이 33(ms)이라는 의미로, 그 숫자만큼 시스템을 일시적으로 정지(사용자의 입력을 기다린다.)
}
}
- webcam으로부터 비디오 읽어옴
int main() {
Mat frame;
// capture from webcam
// whose device number=0
VideoCapture cap(0); // 대부분의 경우 노트북에 부착되어있는 웹캠 디바이스의 넘버가 0임
while (1) {
cap >> frame;
imshow("web cam", frame);
waitKey(16);
}
}
VideoCapture Class에 포함되어있는 다양한 함수들
- grab() : 현재 존재하는 프레임의 다음 프레임을 가져오는 함수
- open(const String & filename) : 특정한 동영상 파일을 읽어오는 함수
- operator>> : 비디오캡쳐 클래스가 가지고있는 동영상의 특정 프레임을 메트릭스에 전달해주게 됨
- get(int propid) const : 비디오가 가지고있는 상세정보를 확인할 수 있다.
현재 비디오 파일의 위치. 몇ms재생되었는지, 프레임의 개수, 가로세로, fps 등등..
int main() {
Mat frame;
VideoCapture cap;
if (cap.open("background.mp4") == 0) return -1;
double fps = cap.get(CAP_PROP_FPS); //fps정보 얻어옴
double time_in_msec = 0; int curr_frame = 0; // 현재 재생되고 있는 시간과 프레임 0으로 초기화
int total_frames = cap.get(CAP_PROP_FRAME_COUNT); // 동영상의 총 프레임 수 확인
// video stops after 3 sec
while (time_in_msec < 3000) { // 최초 3초만을 보겠다는 의미
cap >> frame;
if (frame.empty()) break; // 비디오 끝에 도달했는지 확인, 루프 벗어남..
time_in_msec = cap.get(CAP_PROP_POS_MSEC); // 현재 재생되고 있는 시간 들어감
curr_frame = cap.get(CAP_PROP_POS_FRAMES);
// printing current frames over total frames
cout << "frames: " << curr_frame << " / " << total_frames << endl;
imshow("video", frame);
// calculating the right delay from given fps
waitKey(1000 / fps); // 영상 간의 간격을 알고 싶을 때 사용하는 공식.. (일반적으로) 33 넣는거랑 동일한 효과
}
waitKey(0);
return 0;
}
3. 영상과 동영상을 재생하는 방법
// Display an image
int main() {
Mat img;
img = imread("lena.png", 1); // 영상 읽어옴
imshow("Window", img); // 영상 display(재생)함 (윈도우이름, 재생하고싶은 데이터(메트릭스)
waitKey(0);
}
// Display a video
int main() {
Mat frame;
VideoCapture cap("background.mp4");
while (1) {
cap >> frame;
imshow("Window", frame);
waitKey(30); // 30ms 만큼 기다리겠다. 딜레이주겠다는 의미
}
}
- int waitKey(int delay=0)
Delay in milliseconds
waitKey(0) : 프레임을 일시정지한 것같은 효과. 계속 기다리겠다는 의미
이 게시물은 한동대학교 황성수 교수님의 컴퓨터비전 강의를 공부하며 정리한 내용입니다.
'Computer Vision' 카테고리의 다른 글
[OpenCV] Drawing 함수(Drawing Function) (0) | 2020.01.11 |
---|---|
[OpenCV] Mat 연산자(Mat operator) (0) | 2020.01.11 |
[컴퓨터 비전] 색공간의 이해 (0) | 2020.01.09 |
[컴퓨터 비전] 디지털 영상/ 동영상의 기초 (0) | 2020.01.09 |
[컴퓨터 비전] 컴퓨터비전(Computer Vision)이란? (0) | 2020.01.09 |