지난 번에 함수 실행 시간 측정하는 방법으로 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;
}
그러면 실행 결과는 우리가 예상한 대로 나오게 됩니다.