[w5d3] VideoCapture, 그리기 함수, Trackbar

34707 단어 opencvopencv

(Ubuntu 18.04.6 LTS)
2022.03.16
C++, VS code 사용
프로그래머스 자율주행 데브코스

VideoCaputre class

하드웨어인 카메라와 동영상 파일은 모두 VideoCapture class로 처리함.

// 동영상 파일 불러오기.
#include <iostream>
#include "opencv2/opencv.hpp"

int main()
{
    cv::VideoCapture cap;
    cap.open("./resources/test_video.mp4");

    if (!cap.isOpened())
        return -1;

    cv::Mat frame;
    while (true) {
        cap >> frame;

        if (frame.empty()) break;
        cv::imshow("frame",frame);
        
        if (cv::waitKey(10) >= 0){
            break;
        }
    }
}
//카메라 사용하기
#include <iostream>
#include "opencv2/opencv.hpp"

int main()
{
    cv::VideoCapture cap;
    cap.open(0);

    if (!cap.isOpened())
        return -1;
    
    cv::Mat frame;
    while (true){
        cap.read(frame);
        
        if (frame.empty()) break;

        cv::imshow("frame",frame);

        if (cv::waitKey(1) >= 0)
            break;
        
    }
    return 0;
}

두 코드의 차이는 cap.open()에 index를 넣으면 카메라가 실행되며, 파일 경로를 입력하면 동영상을 입력받음. index 0은 기본 설정 카메라로, 노트북에서 사용하면 웹캠이 일반적으로 켜짐.

Videocap 객체에서 get과 set을 이용해 해당 객체의 property를 얻을 수 있음.

  • CAP_PROP_FRAME_WIDTH
  • CAP_PROP_FRAME_HEIGHT
  • CAP_PROP_FPS
  • CAP_PROP_FRAME_COUNT: 전체 프레임 수.
  • CAP_PROP_POS_FRAMES: 현재 프레임 수.
  • CAP_PROP_EXPOSURE: 노출
cap.get(CAP_PROP_FRAME_WIDTH)

VideoWriter class

프레임을 저장하기 위한 클래스.

cv::VideoWriter::VideoWriter 	( 	const String &  	filename,
		int  	fourcc,
		double  	fps,
		Size  	frameSize,
		bool  	isColor = true 
	) 	

filename은 파일 이름, fps는 초당 프레임 수, framSize는 비디오 프레임 크기, isColor는 컬러 동영상 플래그, fourcc는 압축 방식을 나타내는 4개 문자로, VideoWriter::fourcc()함수로 생성. 대표적인 예는 아래와 같음.

- VideoWriter::fourcc('D','I','V','X')
- VideoWriter::fourcc('X','V','I','D')
- VideoWriter::fourcc('M','J','P','G')
// 예시 코드
#include <iostream>
#include "opencv2/opencv.hpp"

int main()
{
    cv::VideoCapture cap(0);
    if (!cap.isOpened()){
        std::cerr << "Camera open failed!" << std::endl;
        return -1;
    }

    int fourcc = cv::VideoWriter::fourcc('X','V','I','D');
    double fps = 15;
    cv::Size sz = cv::Size((int)cap.get(cv::CAP_PROP_FRAME_WIDTH),(int)cap.get(cv::CAP_PROP_FRAME_HEIGHT));

    std::cout << "FPS = " << fps << ", Size: " << sz << std::endl;
    //fps, size를 출력
    
    cv::VideoWriter outputVideo("./resources/output.avi",fourcc,fps,sz);
    cv::VideoWriter CannyVideo("./resources/canny2.avi",fourcc,fps,sz);
    
    if (!outputVideo.isOpened() || !CannyVideo.isOpened()){
        std::cerr << "output files open failed!" << std::endl;
        return -2;
    }
    //예외 처리 코드
    
    int delay = cvRound(1000/fps);
    cv::Mat frame, edge;

    cv::VideoCapture vid_origin;
    // 기존 영상을 불러들임.
    vid_origin.open("./resources/origin.avi");
    
    if(!vid_origin.isOpened()){
        std::cerr << "vid origin open failed!" << std::endl;
        //origin이 없을 경우 출력.
    }

    while (true) {
        vid_origin >> frame;
        if (frame.empty()) break;
        CannyVideo << frame;
        //기존 영상을 먼저 저장. (origin.avi)
    }

    while (true) {
    	cap >> frame;
        outputVideo << frame;
        cv::Canny(frame,edge,50,150);
        //edge detection
        cv::cvtColor(edge,edge,cv::COLOR_GRAY2BGR);
        // edge detction 사용한 파일을 BGR 형태로 표현하기 위해 cvtColor 사용
        CannyVideo << edge;
        imshow("frame",frame);
        imshow("edge",edge);

        if (cv::waitKey(delay) == 27) break;
        //ASCII code 27 == esc

        }
    std::cout << "files are saved" << std::endl;
    cap.release();
    cv::destroyAllWindows();
}

그리기 함수

InputOutputArray에 Mat type의 이미지를 넣고, 나머지는 해당 그리는 타입마다 차이가 있다.
line은 Point 2개를 잇는 함수, polylines는 여러개의 점을 잇는 함수이며 isClosed를 true로 설정하면 닫힌 형태로 나타난다. rectangle은 양 끝점을 이용한 직사각형, putText는 주어진 Point가 문장의 가장 왼쪽 아래가 된다. putText의 폰트는 Hershey font에 해당하는 부분만 가능하다.

void cv::line 	( 	InputOutputArray  	img,
		Point  	pt1,
		Point  	pt2,
		const Scalar &  	color,
		int  	thickness = 1,
		int  	lineType = LINE_8,
		int  	shift = 0 
	) 		
    
void cv::polylines 	( 	InputOutputArray  	img,
		InputArrayOfArrays  	pts,
		bool  	isClosed,
		const Scalar &  	color,
		int  	thickness = 1,
		int  	lineType = LINE_8,
		int  	shift = 0 
	) 		
    
void cv::rectangle 	( 	InputOutputArray  	img,
		Point  	pt1,
		Point  	pt2,
		const Scalar &  	color,
		int  	thickness = 1,
		int  	lineType = LINE_8,
		int  	shift = 0 
	) 	
void cv::putText 	( 	InputOutputArray  	img,
		const String &  	text,
		Point  	org,
		int  	fontFace,
		double  	fontScale,
		Scalar  	color,
		int  	thickness = 1,
		int  	lineType = LINE_8,
		bool  	bottomLeftOrigin = false 
	) 		

자세한 내용은 아래의 공식 사이트에서 더 확인할 수 있다.
함수: https://docs.opencv.org/4.x/d6/d6e/group__imgproc__draw.html#gaf076ef45de481ac96e0ab3dc2c29a777
폰트: https://docs.opencv.org/4.x/d6/d6e/group__imgproc__draw.html#ga0f9314ea6e35f99bb23f29567fc16e11

라인 타입 이미지 확인은 아래에서 가능하며 작성 가능한 코드는 아래와 같다.
https://www.oreilly.com/library/view/mastering-opencv-4/9781789344912/5c4150d2-b550-40be-8b18-f2e71e20d9be.xhtml

cv::LineTypes {
  cv::FILLED = -1,
  cv::LINE_4 = 4,
  cv::LINE_8 = 8,
  cv::LINE_AA = 16
}

Trackbar

createTrackbar()
int cv::createTrackbar 	( 	const String &  	trackbarname,
		const String &  	winname,
		int *  	value,
		int  	count,
		TrackbarCallback  	onChange = 0,
		void *  	userdata = 0 
	) 		

trackbar 이름을 설정하고, winname에 해당하는 창에 trackbar를 만든다.
int * value는 트랙바의 초기 위치를 결정한다. 0으로 둘 경우 0으로 시작.
trackbar의 최소값은 0이며 최대값은 count에 지정한 값이다.
onChange는 trackbar 값이 변경될 때마다 호출되는 함수를 지정하는 부분이다.
userdata는 호출되는 함수에서 외부 값을 사용하기 위한 데이터를 불러오기 위한 포인터로 호출 함수의 인자로 들어간다.

#include <iostream>
#include "opencv2/opencv.hpp"

void on_level_change(int pos, void*userdata);

int main()
{
    int a = 128;
    cv::Mat img = cv::Mat::zeros(480,640,CV_8UC1);
    cv::namedWindow("img");
    cv::createTrackbar("level","img",&a,255,on_level_change,(void*)&img);

    cv::imshow("img",img);
    cv::waitKey();
}

void on_level_change(int pos, void*userdata){
    cv::Mat img = *(cv::Mat*)userdata;
    img.setTo(pos);
    cv::imshow("img",img);
}


코드 결과 출력은 위와 같다.

void on_level_change(int pos, void* userdata){
    cv::Mat img = *(cv::Mat*)userdata;
    img.setTo(pos);
    cv::imshow("img",img);
}

트랙바 호출 시 사용하는 함수의 인자로 int pos, void* userdata를 사용하였다. pos는 트랙바 함수의 호출 시 트랙 바의 현재 위치를 값으로 가지게 되며, userdata는 create_Trackbar 함수의 userdata 부분을 통해 받아와 사용한다.

// 추후 마우스 이벤트 마저 작성..

좋은 웹페이지 즐겨찾기