头文件:opencv2/imgproc/imgproc.hpp
**作用:**获取图像像素点值
opencv3中图形存储基本为Mat格式,如果我们想获取像素点的灰度值或者RGB值,可以通过image.at
Mat类中的at方法对于获取图像矩阵某点的RGB值或者改变某点的值很方便,对于单通道的图像,则可以使用:
image.at<uchar>(i, j)
其中有一个要注意的地方是i对应的是点的y坐标,j对应的是点的x坐标,而不是我们习惯的(x,y)
来获取或改变该点的值,而RGB通道的则可以使用:
image.at<Vec3b>(i, j)[0]
image.at<Vec3b>(i, j)[1]
image.at<Vec3b>(i, j)[2]
来分别获取B、G、R三个通道的对应的值。下边的代码实现对图像加椒盐噪声:
#include
#include
using namespace std;
using namespace cv;
void salt_noise( Mat image, int time );
int main ( int argc, char** argv )
{
Mat image = imread("C:\\Users\\Administrator\\Desktop\\2-1.jpg",0);
if ( image.empty() ){
cout << "Load image error" << endl;
return -1;
}
salt_noise(image, 3000);
namedWindow("image", 1);
imshow("image", image);
waitKey();
return 0;
}
void salt_noise ( Mat image, int time )
{
for (int k = 0; k < time; k++ ) //time is the number of noise you add
{
int i = rand() % image.rows;
int j = rand() % image.cols;
if (image.channels() == 1) //single channel
{
image.at<uchar>(i,j) = rand() % 255;
}
else if (image.channels() == 3) //RGB channel
{
image.at<Vec3b>(i, j)[0] = rand() % 255;
image.at<Vec3b>(i, j)[1] = rand() % 255;
image.at<Vec3b>(i, j)[2] = rand() % 255;
}
}
}
还有比较省时的方法使用Mat的模板子类Mat_
Mat_<uchar> img = image;
img(i, j) = rand() % 255;
对于RGB通道的使用:
Mat_<Vec3b> img = image;
img(i, j)[0] = rand() % 255;
img(i, j)[1] = rand() % 255;
mg(i, j)[2] = rand() % 255;
还可以用指针的方法遍历每一像素:(耗时较小)
void colorReduce(Mat image, int div = 64)
{
int nrow = image.rows;
int ncol = image.cols*image.channels();
for (int i = 0; i < nrow; i++)
{
uchar* data = image.ptr<uchar>(i);//get the address of row i;
for (int j = 0; j < ncol; j++)
{
data[i] = (data[i] / div)*div ;
}
}
}
我们要尤其注意OpenCV坐标系与row&col的关系 (Mat::at(x,y)和Mat::at(Point(x, y))的区别)
直接给出对应关系吧
row == heigh == Point.y
col == width == Point.x
Mat::at(Point(x, y)) == Mat::at(y,x)
因为还有点的坐标,所以建议在访问时都用Mat::at(Point(x, y))这种形式吧,免去了点坐标和行列的转换
详细说明: