본문 바로가기

프로그래밍 강좌/C++ - OpenCV

[OpenCV][C++] 함수 실행 시간 측정 쉬운 방법 - TickMeter 사용법 총정리 elapsed time chrono getTimeMilli reset blur

지난 번에 함수 실행 시간 측정하는 방법으로 chrono 라이브러리를 사용하는

이번에는 OpenCV를 사용할 때 함수의 실행 시간정말 쉽게 측정할 수 있는 방법을 알려드릴께요.

 

cv::TickMeter 클래스

이름에서 풍기는 스멜 그대로~

함수의 연산시간을 측정할 수 있는 클래스에요.

OpenCV utility.hpp에 있는 TickMeter 클래스를 다시 써 보면 아래와 같습니다.

멤버 변수로 startTime, sumTime, 그리고 counter가 있어요. startTime과 sumTime은 시간 계산할 때 사용되는 것이고, counter start(), stop() 불린 횟수로 평균 수행 시간인 getAvgTimeMilli()를 계산할 때 사용됩니다.

측정 시간 Micro, Milli, Sec 단위로 측정이 가능합니다.

제가 측정해보니 우리가 일반적으로 함수 시간을 측정할 때에는 부족함 없이 사용이 가능할 듯 합니다.

사용 방법은 간단합니다. 초시계처럼 생각을 하시면 됩니다.

TickMeter 객체인 tm을 생성하고 아래와 같이 함수의 시작과 끝에서 start(), stop()을 불러주시면 측정이 됩니다.

cv::TickMeter tm;
tm.start();
//함수 실행
tm.stop();
double ms = tm.getTimeMilli();
 

그럼 예시를 한번 보겠습니다.

영상을 하나 불러와서 blur 시키는 함수를 5회 수행한 후 시간을 측정해 봤어요.

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

int main()
{
	cv::Mat src = cv::imread("lena_gray.bmp", cv::IMREAD_GRAYSCALE);
	cv::Mat dst;
	cv::TickMeter tm;
	tm.start();
	for (int i = 0; i < 5; ++i) {
		cv::blur(src, dst, cv::Size(5, 5));
	}
	tm.stop();

	std::cout << "Elapsed Time: " << tm.getTimeMilli() << " ms" << std::endl;

	return 0;
}
 

결과는 아래와 같이 나오네요. 단위는 100 ns 단위까지 측정이 됩니다.

더 빠른 단위의 측정(예를 들어 nano sec. 까지 측정이 필요하면)을 원한다면 chrono 클래스를 사용하셔야 겠네요.

여기까지만 보면 너무 아쉽죠? 그래도 클래스 관련 총정리인데요.

 

꿀팁~!! 공개 합니다.

 

아까 TickMeter 클래스에 counter 변수가 있다고 했죠?

아래와 같이 getAvgTimeMilli()를 사용하시면 평균 측정 시간을 쉽게 계산할 수 있어요.

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

int main()
{
	cv::Mat src = cv::imread("lena_gray.bmp", cv::IMREAD_GRAYSCALE);
	cv::Mat dst;
	cv::TickMeter tm;
	
	for (int i = 0; i < 5; ++i) {
		tm.start();
		cv::blur(src, dst, cv::Size(5, 5));
		tm.stop();
	}	

	std::cout << "Elapsed Time(Total): " << tm.getTimeMilli() << " ms" << std::endl;
	std::cout << "Elapsed Time(Avg): " << tm.getAvgTimeMilli() << " ms" << std::endl;

	return 0;
}
 

수행 결과는 아래와 같습니다.

주의하셔야 할 것!!

여러 함수를 측정해야 할 때 어떻게 사용해야 할까요?

 

아래 소스를 한번 보시죠.

첫번째 blur 함수는 kernel size가 31x31이고 두번째 blur 함수는 kernel size가 5x5 입니다. 분명히 kernel size가 작으면 더 빨라야 하는데 결과를 한번 볼까요?

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

int main()
{
	cv::Mat src = cv::imread("lena_gray.bmp", cv::IMREAD_GRAYSCALE);
	cv::Mat dst;
	cv::TickMeter tm;

	tm.start();	
	cv::blur(src, dst, cv::Size(31, 31));			
	tm.stop();
	std::cout << "Elapsed Time(blur_31): " << tm.getTimeMilli() << " ms" << std::endl;

	tm.start();
	cv::blur(src, dst, cv::Size(5, 5));
	tm.stop();
	std::cout << "Elapsed Time(blur_5): " << tm.getTimeMilli() << " ms" << std::endl;

	return 0;
}
 

결과는 아래와 같습니다.

5x5가 더 오래 걸린 것처럼 나옵니다.

이 OpenCV의 TickMeter stop()은 실제 초시계로 생각하면 stop이 아니라 pause에 가깝습니다. 그래서 위 처럼 하면 두번째 측정 시간은 (31x31 실행 시간) + (5x5 실행 시간) 이 측정이 된 것 입니다.

각 함수별 정확한 수행 시간 측정을 하시기 위해서는 중간에 reset()을 한번 해 주셔야 합니다. 아니면 TickMeter를 여러개 만드셔도 됩니다.

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

int main()
{
	cv::Mat src = cv::imread("lena_gray.bmp", cv::IMREAD_GRAYSCALE);
	cv::Mat dst;
	cv::TickMeter tm;

	tm.start();	
	cv::blur(src, dst, cv::Size(31, 31));			
	tm.stop();
	std::cout << "Elapsed Time(blur_31): " << tm.getTimeMilli() << " ms" << std::endl;
	tm.reset();
	tm.start();
	cv::blur(src, dst, cv::Size(5, 5));
	tm.stop();
	std::cout << "Elapsed Time(blur_5): " << tm.getTimeMilli() << " ms" << std::endl;

	return 0;
}
 

그러면 실행 결과는 우리가 예상한 대로 나오게 됩니다.