操作单个像素:
at()用來訪問像素,可返回左值或右值,所以我們可用at()得到或改變某個像素值,這函式使用模板,所以使用時除了輸入位置,還必須需入影像的像素型態,使用at()函式時,輸入參數順序同樣為先高再寬。。
- OpenCV改變像素:template T& Mat::at(int i, int j)
- OpenCV讀取像素:template const T& Mat::at(int i, int j) const
- 在灰階圖中,OpenCV裡可用uchar代替uncigned char,在彩色圖中,OpenCV裡可用Vec3b代替將3個uchar組成的容器(vector),且可在後面加上[],註明是要操作此像素的哪個通道。
下面操作一個8位元灰階圖,分別改變某個像素的值,以及查看此像素的值:
Mat gray_img(100, 100, CV_8U, Scalar(100)); gray_img.at<uchar>(30,20) =255; uchar value1 = gray_img.at<uchar>(30,20);
下面分別改變彩色圖某個像素的第一通道值,以及查看此像素第一通道的值:
Mat color_img(100, 100, CV_8UC3, Scalar(200,100,0)); img.at<Vec3b>(30,20)[0] =255; uchar value2 = img.at<Vec3b>(30,20)[0];
操作像素
ptr函式輸入指定列,返回一個指標指向此列的第一個像素,通常為尋訪影像用到,ptr可讀取或改變像素值,同樣使用模板,所以也必須需入影像的像素型態。
- OpenCV改變像素:template T* Mat::ptr(int i=0)
- OpenCV讀取像素:template const T* Mat::ptr(int i=0) const
操作多像素(像素巡访)(at、ptr)
当我们进行图片处理是,可能需要遍历所有像素,比如我们改变一张图的灰度值,让所有的像素增加30,这时候我们就需要遍历整个图片的所有像素,这边介绍OpenCV的三种方法(1, at() 2, ptr() 3, 迭代器)来遍历Mat所有像素.
- at() 可用来读取和修改某个像素值,通常对随机位置的像素进行读写,就效率 而言并不适合用来遍历所有像素
示例: 让所有像素加10;
int widthLimit = img.channels()*img.colos; for(int height=0; height<img.rows; height++) { for(int width=0; width<widthLimit; width++) { img.at<uchar>(height,width) += 10; } }
ptr()函数返回指针,指向图片指定列的首像素,使用时需要输入像素深度和第几列,对于一个深度8位元的图,我们可以用img.ptr(j)指定第j列的第一个像素,接着逐列遍历,最后访问到所有像素,这种方法运行速度比at()快,在解析度大或是重视效率的地方是比较好的方法,以下是用ptr()来读取img的所有像素,并让所有像素值加10:
int widthLimit = img.channels()* img.colos; for(int height=0; height<img.rows; height++){ uchar* data = img.ptr<uchar>(height); for(int width=0; width< widthLimit; width++){ data[width] +=10; } }
迭代器方法
OpenCV有为Mat提供与STL迭代器兼容的迭代器,使用时需指定数据类型,以下示例是用迭代器来访问img的所有像素,并让所有像素值增加10:
if(img.channels()==1) { Mat_<uchar>::iterator it = img.begin<uchar>(); Mat_<uchar>::iterator itend = img.end<uchar>(); for(; it != itend; it++){ (*it) += 10; } }else if(img.channels()==3) { Mat_<Vec3b>::iterator it = img.begin<Vec3b>(); Mat_<Vec3b>::iterator itend = img.end<Vector>(); for(;it != itend; it++){ (*it)[0] += 10; (*it)[1] += 10; (*it)[2] += 10; } }