opencv 矩阵元素不同获取方式及其效率对比
2016-04-15 14:38
459 查看
opencv 矩阵数据Mat元素获取有四种方式: 直接获取、模板方式、行指针方式、元素地址方式。 测试发现在O3优化方式下直接获取和元素地址访问这两中方式效率最高, 其效率为模板和行指针方式的两倍。 在没有优化的方式下符合一般常识,元素地址访问和行指针方式效率最高。
测试代码如下:
代码中CwTimer 是一个时间类,可以方便测试程序运行时间, 该类是从网络中获取, 作者为 程明明。 其实现如下。
利用O3优化:
g++ test.cpp -O3 -o test `pkg-config --cflags --libs opencv`程序运行结果如下, 发现直接获取元素和地址访问速度基本一样,但是模板获取和行指针的方式效率只有其他两种的一般。这个和一般性常识不符,一般认为按照行指针获取的效率会和元素地址获取方式持平。
不利用优化:
g++ test.cpp -g -o test `pkg-config --cflags --libs opencv`
得出结果如下:
可以看出此时的性能符合一般常识。
测试代码如下:
#include <string> #include <iostream> #include <time.h> using namespace cv; using namespace std; #include "CwTimer.hpp" int main( int argc, const char** argv ) { //矩阵总共获取次数 uint32_t num = 10000; Mat m(100, 100, CV_64F, Scalar(0)); //定义矩阵模板 Mat_<double> m_ = m; uint32_t h = m.rows, w = m.cols; //直接获取方式 CwTimer tm0("direct"); for(int i = 0; i < num; i++) { tm0.Start(); for(int p = 0; p < h; p++) { for(int q = 0; q < w; q++) { m.at<float>(p, q) = 13; double tm = m.at<double>(p, q); } } tm0.Stop(); } tm0.Report(); //模板获取方式 CwTimer tm3("template"); for(int i = 0; i < num; i++) { tm3.Start(); for(int p = 0; p < h; p++) { for(int q = 0; q < w; q++) { m_(p, q) = 13; double tm = m_(p, q); } } tm3.Stop(); } tm3.Report(); //行指针获取方式 CwTimer tm1("row_ptr"); for(int i = 0; i < num; i++) { tm1.Start(); for(int p = 0; p < h; p++) { double * pm = m.ptr<double>(p); for(int q = 0; q < w; q++) { pm[q] = 13; double tm = pm[q]; } } tm1.Stop(); } tm1.Report(); //元素地址获取方式 CwTimer tm2("address"); for(int i = 0; i < num; i++) { tm2.Start(); double * pdata = (double*)m.data; for(int p = 0; p < h * w; p++) { pdata[p] = 13; double tm = pdata[p]; } tm2.Stop(); } tm2.Report(); return 1; }
代码中CwTimer 是一个时间类,可以方便测试程序运行时间, 该类是从网络中获取, 作者为 程明明。 其实现如下。
#pragma once #pragma warning(disable:4512) class CwTimer { public: CwTimer(string t = "Timer"):title(t) { is_started = false; start_clock = 0; cumulative_clock = 0; n_starts = 0; } ~CwTimer(){ if (is_started) printf("CwTimer '%s' is started and is being destroyed.\n", title.c_str()); } inline void Start(); inline void Stop(); inline void Reset(); inline bool Report(); inline bool StopAndReport() { Stop(); return Report(); } inline float TimeInSeconds(); inline float AvgTime(){assert(is_started == false); return TimeInSeconds()/n_starts;} private: string title; bool is_started; clock_t start_clock; clock_t cumulative_clock; unsigned int n_starts; }; /************************************************************************/ /* Implementations */ /************************************************************************/ void CwTimer::Start() { if (is_started){ printf("CwTimer '%s' is already started. Nothing done.\n", title.c_str()); start_clock = clock(); return; } is_started = true; n_starts++; start_clock = clock(); } void CwTimer::Stop() { if (!is_started){ printf("CwTimer '%s' is started. Nothing done\n", title.c_str()); return; } cumulative_clock += clock() - start_clock; is_started = false; } void CwTimer::Reset() { if (is_started) { printf("CwTimer '%s'is started during reset request.\n Only reset cumulative time.\n", title.c_str()); return; } cumulative_clock = 0; } bool CwTimer::Report() { if (is_started){ printf("CwTimer '%s' is started.\n Cannot provide a time report.", title.c_str()); return false; } float timeUsed = TimeInSeconds(); printf("[%s] CumuTime: %4gs, #run: %2d, AvgTime: %4gs\n", title.c_str(), timeUsed, n_starts, timeUsed/n_starts); return true; } float CwTimer::TimeInSeconds() { if (is_started){ printf("CwTimer '%s' is started. Nothing done\n", title.c_str()); return 0; } return float(cumulative_clock) / CLOCKS_PER_SEC; }
利用O3优化:
g++ test.cpp -O3 -o test `pkg-config --cflags --libs opencv`程序运行结果如下, 发现直接获取元素和地址访问速度基本一样,但是模板获取和行指针的方式效率只有其他两种的一般。这个和一般性常识不符,一般认为按照行指针获取的效率会和元素地址获取方式持平。
不利用优化:
g++ test.cpp -g -o test `pkg-config --cflags --libs opencv`
得出结果如下:
可以看出此时的性能符合一般常识。
相关文章推荐
- python中使用OpenCV进行人脸检测的例子
- opencv 做人脸识别 opencv 人脸匹配分析
- 使用opencv拉伸图像扩大分辨率示例
- 基于C++实现kinect+opencv 获取深度及彩色数据
- OpenCV 2.4.3 C++ 平滑处理分析
- Python中使用OpenCV库来进行简单的气象学遥感影像计算
- 利用Python和OpenCV库将URL转换为OpenCV格式的方法
- python结合opencv实现人脸检测与跟踪
- Python环境搭建之OpenCV的步骤方法
- Python实现OpenCV的安装与使用示例
- 在树莓派2或树莓派B+上安装Python和OpenCV的教程
- opencv-python学习一--人脸检测
- 在Ubuntu上安装OpenCV3.0和Python-openCV的经历
- OpenCV配置,从来没有这么简单!
- ubuntu下opencv和qt的安装配置
- OpenCV学习笔记(二十五)——OpenCV图形界面设计Qt+VS2008
- 分享一些OpenCV实现立体视觉的经验
- 关于OpenCv图像变换与基本图形检测
- "应用程序正常初始化失败"-0xc0150002 解决办法
- OpenCV->HSV色彩空间