今天百度搜資料還搜到了自己的。。。《訪問圖像中每個像素的值》,這是之前寫的了,用的也是2.0的風格IplImage*格式,不太適用後來Mat的格式,特此重寫一篇。
以下例子源自《The OpenCV Tutorials --Release 2.4.2》2.2 How to scan images, lookup tables and time measurement with OpenCV
圖像容器Mat
訪問圖像中的像素
高效的方法:C操作符[ ]
- Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
- {
- // accept only char type matrices
- CV_Assert(I.depth() != sizeof(uchar));
- int channels = I.channels();
- int nRows = I.rows ;
- int nCols = I.cols* channels;
- 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]];
- }
- }
- return I;
- }
- int nRows = I.rows * channels;
- int nCols = I.cols;
- uchar* p = I.data;
- for( unsigned int i =0; i < ncol*nrows; ++i)
- *p++ = table[*p];
安全的方法:迭代器iterator
相比用指針直接訪問可能出現越界問題,迭代器絕對是非常安全的方法:- Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
- {
- // accept only char type matrices
- CV_Assert(I.depth() != sizeof(uchar));
- 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]];
- }
- }
- }
- return I;
- }
這種方式雖然安全,但是挺慢的,一會兒就知道了。
更慢的方法:動態地址計算
- Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)
- {
- // accept only char type matrices
- CV_Assert(I.depth() != sizeof(uchar));
- 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;
- }
- }
- return I;
- }
減小顏色空間 color space reduction
0~9 範圍的像素值爲 0
10~19 範圍的像素值 爲 10
20~29 範圍的像素值爲 20
。。。。。。
着這樣的操作將顏色取值降低爲 26*26*26 種情況。這個操作可以用一個簡單的公式:
在處理圖像像素時,每個像素需要進行一遍上述計算也需要一定的時間花銷。但我們注意到其實只有 0~255 種像素,即只有256種情況。進一步可以把256種計算好的結果提前存在表中 table 中,這樣每種情況不需計算直接從 table 中取結果即可。
- int divideWith=10;
- uchar table[256];
- for (int i = 0; i < 256; ++i)
- table[i] = divideWith* (i/divideWith);
- p[j] = table[p[j]];
LUT : Look up table
OpenCV 很聰明的有個 LUT 函數就是針對這種 Look up talbe 的操作:- Mat lookUpTable(1, 256, CV_8U);
- uchar* p = lookUpTable.data;
- for( int i = 0; i < 256; ++i)
- p[i] = table[i];
- for (int i = 0; i < times; ++i)
- LUT(I, lookUpTable, J);
算法計時
- double t;
- t = (double)getTickCount();
- t = 1000*((double)getTickCount() - t)/getTickFrequency();
- t /= times;