测试代码:opencv\samples\cpp\tutorial_code\core\how_to_scan_images
cv::getTickCount() the number of clock cycle
cv::getTickFrequency() the number of cycles per seconds
1
2
3
4 |
double
t = ( double )getTickCount(); // 做点什么 ... t = (( double )getTickCount() - t)/getTickFrequency(); cout << "Times passed in seconds: "
<< t << endl; |
以颜色缩减为例,可通过查找表替换颜色从而缩减存储,查找表构建方法:
1
2
3 |
uchar table[256]; for
( int i = 0; i < 256; ++i) table[i] = divideWith* (i/divideWith); |
有以下几种访问像素方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 |
int nRows = I.rows * I.channels(); int nCols = I.cols; if (I.isContinuous()) { nCols *= nRows; nRows = 1; } int
i,j; uchar* p; for ( i = 0; i < nRows; ++i) { p = I.ptr<uchar>(i); for
( j = 0; j < nCols; ++j) { p[j] = table[p[j]]; } } |
我们获取了每一行开始处的指针,然后遍历至该行末尾。如果矩阵是以连续方式存储的,我们只需请求一次指针、然后一路遍历下去就行。彩色图像的情况有必要加以注意:因为三个通道的原因,我们需要遍历的元素数目也是3倍。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 |
const
int channels = I.channels(); switch (channels) { case
1: { MatIterator_<uchar> it, end; for ( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it) *it = table[*it]; break ; } case
3: { MatIterator_<Vec3b> it, end; for ( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it) { (*it)[0] = table[(*it)[0]]; (*it)[1] = table[(*it)[1]]; (*it)[2] = table[(*it)[2]]; } } } |
在cv::Mat_的子类中,下划线表示这是一个模板类。OpenCV将Mat设计为一个容器,可以这样声明迭代器:
1
2
3
4 |
cv::MatIterator_<cv::Vec3b> it; cv::Mat_<cv::Vec3b>::iterator it; // 之后就可以使用begin()和end()等方法了 cv::Mat_<cv::Vec3b>::iterator it= image.begin<cv::Vec3b>(); |
Mat_类型在使用begin和end方法时可以不加类型:
1
2
3 |
cv::Mat_<cv::Vec3b> cimage= image; cv::Mat_<cv::Vec3b>::iterator it= cimage.begin(); cv::Mat_<cv::Vec3b>::iterator itend= cimage.end(); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 |
const
int channels = I.channels(); switch (channels) { case
1: { for ( int
i = 0; i < I.rows; ++i) for ( int
j = 0; j < I.cols; ++j ) I.at<uchar>(i,j) = table[I.at<uchar>(i,j)]; break ; } case
3: { Mat_<Vec3b> _I = I; for ( int
i = 0; i < I.rows; ++i) for ( int
j = 0; j < I.cols; ++j ) { _I(i,j)[0] = table[_I(i,j)[0]]; _I(i,j)[1] = table[_I(i,j)[1]]; _I(i,j)[2] = table[_I(i,j)[2]]; } I = _I; break ; } } |
注意:当且仅当在 debug 模式下 它会检查你的输入坐标是否有效或者超出范围。
cv::Mat_类型可以直接用operator()访问像素,省略.at(),少写两个字。
1
2 |
cv::Mat_<uchar> im2= image; // im2 refers to image im2(50,100)= 0; // access to row 50 and column 100 |
1
2
3
4
5 |
Mat lookUpTable(1, 256, CV_8U); uchar* p = lookUpTable.data; for ( int
i = 0; i < 256; ++i) p[i] = table[i]; LUT(I, lookUpTable, J); |
对于一个给定的值,将其替换成其他的值是一个很常见的操作,OpenCV 提供里一个函数直接实现该操作,并不需要你自己扫描图像,就是:operationsOnArrays:LUT() <lut> ,一个包含于core module的函数。
4. LUT > 1. Efficient way > 2. Iterator > 3. On-The-Fly random access
输入:600*450
输出:
1
2
3
4 |
Time of reducing with the C operator [] (averaged for
100 runs): 4.05264 milliseconds. Time of reducing with the iterator (averaged for
100 runs): 137.583 milliseconds. Time of reducing with the on-the-fly address generation - at function (averaged for
100 runs): 255.371 milliseconds. Time of reducing with the LUT function (averaged for
100 runs): 3.51129 milliseconds. |
结论: 尽量使用 OpenCV 内置函数. 调用LUT 函数可以获得最快的速度. 这是因为OpenCV库可以通过英特尔线程架构启用多线程.
OpenCV学习笔记(三) 访问像素,布布扣,bubuko.com
原文:http://www.cnblogs.com/ericxing/p/3576747.html