生活随笔
收集整理的這篇文章主要介紹了
Opencv中三种操作像素的方法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
測試環境:opencv3.1.0 + Visual Studio 2015 + win7 64位
?
opencv中有3中方法可以訪問/修改圖像的像素值,分別為:
1.??????指針訪問
2.??????迭代器iterator
3.??????動態地址計算
?
測試程序如下:
#include "opencv2/opencv.hpp" #include "iostream" using namespace std ;using namespace cv; int main () { Mat image (240 , 320 , CV_8UC3, Scalar(0 , 0 , 0 ) ) ; imshow("原始圖像" , image); double start = static_cast <double >(getTickCount()); int rowNumber = image.rows; int colNumber = image.cols * image.channels(); for (int i = 0 ; i < rowNumber; i++) { uchar* data = image.ptr<uchar>(i); for (int j = 0 ; j < colNumber; j++) { data[j] = 255 ; } } double end = static_cast <double >(getTickCount()); double time = (end - start) / getTickFrequency(); cout << "指針操作運行時間為:" << time << "秒" << endl ; imshow("指針操作" , image); start = static_cast <double >(getTickCount()); Mat_<Vec3b>::iterator it = image.begin<Vec3b>(); Mat_<Vec3b>::iterator itend = image.end<Vec3b>(); for (; it != itend; it++) { (*it)[0 ] = 255 ; (*it)[1 ] = 255 ; (*it)[2 ] = 0 ; } end = static_cast <double >(getTickCount()); time = (end - start) / getTickFrequency(); cout << "迭代器操作運行時間為:" << time << "秒" << endl ; imshow("迭代器操作" , image); start = static_cast <double >(getTickCount()); rowNumber = image.rows; colNumber = image.cols; for (int i = 0 ; i < rowNumber; i++) for (int j = 0 ; j < colNumber; j++) { image.at<Vec3b>(i, j)[0 ] = 0 ; image.at<Vec3b>(i, j)[1 ] = 255 ; image.at<Vec3b>(i, j)[2 ] = 0 ; } end = static_cast <double >(getTickCount()); time = (end - start) / getTickFrequency(); cout << "動態地址操作運行時間為:" << time << "秒" << endl ; imshow("動態地址操作" , image); cvWaitKey(0 ); return 1 ; }
運行結果如下:
Debug模式下運行時間如下:
Release模式下運行時間如下:
可以看到指針操作在Debug模式和Release模式下均是最快的,動態地址和迭代器操作稍微慢點。
?
一些說明:
1.??????RGB顏色模型的矩陣如下(opencv中通道順序為BGR):
因此,指針操作的時候,每行的元素個數為:列數 x 通道數。
Mat類提供了ptr函數可以得到圖像任意行的首地址。
?
2.??????在迭代法中,我們所需要做的僅僅是獲得圖像矩陣的begin和end,然后迭代從begin到end。將*操作符添加在迭代指針前,即可以訪問當前指向的內容。相比于指針直接訪問可能出現越界問題,迭代器絕對是非常安全 的方法。
3.??????成員函數at(int y, int x)可以用來存取圖像元素,但是必須在編譯期知道圖像的數據類型。對于彩色圖像,每個像素由三個部分構成:藍色通道、綠色通道和紅色通道(BGR)。因此,對于一個包含彩色圖像的Mat,會返回一個由三個8位數組成的向量。Opencv將此類型的向量定義為Vec3b,即由三個unsigned char組成的向量。這也解釋了為什么存取彩色圖像像素的代碼可以寫出如下形式
image.at<Vec3b>(j, i)[channel] = value;
另外:
而對于單通道的灰度圖像就簡單很多了:
image.at<uchar>(i,j);?
這里要注意at中(i,j)的順序表示的是第i行第j列,跟Point(i,j)和Rect(i,j)中表示第j行第i列是相反的,如果把這個搞混了,很容易導致內存異常,還不容易發現錯誤。
?
補充說明一下:OpenCV中坐標體系中的零點坐標定義為圖片的左上角,X軸為圖像矩形的上面那條水平線,從左往右;Y軸為圖像矩形左邊的那條垂直線,從上往下。在Point(x,y)和Rect(x,y)中,第一個參數x代表的是元素所在圖像的列數,第二個參數y代表的是元素所在圖像的行數,而在at(x,y)中是相反的。
參考文獻
OpenCV3編程入門
OpenCV坐標系與操作像素的四種方法
總結
以上是生活随笔 為你收集整理的Opencv中三种操作像素的方法 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。