操作单个像素:
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 width Limit = img.channels()* img.colos;
for(int height=0; height<img.rows; height++>){
uchar* data = img.ptr<uchar>(height);
for(int width=0; width< img.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;
}
}