opencv01-像素的访问
对于opencv像素的访问,可以有很多种方法,不同的访问方式有着不同的效率。
下面我们将用不同的访问像素的方法来对图像随机加一些椒盐噪声。
- 方法一:
void salt(Mat &img, int n){
for (int k = 0; k < n; k++){ //添加k个随机噪声
int i = rand() % img.cols;//其随机域为0~img.cols-1
int j = rand() % img.rows;
if (img.channels() == 1){ //灰度图像
img.at<uchar>(j, i) = 255;
}
else if (img.channels() == 3){
img.at<Vec3b>(j, i)[0] = 255; //B
img.at<Vec3b>(j, i)[1] = 255; //G
img.at<Vec3b>(j, i)[2] = 255; //R
}
}
}
方法一是通过img.at实现访问,灰度图像每个像素是uchar类型,所以是img.at< uchar>(j, i)。而RGB图像有三个通道,每个通道的像素也是uchar类型,因此是Vec3b。
- 方法二
void salt2(Mat &img, int n){
for (int k = 0; k < n; k++){
int i = rand() % img.rows;//其随机域为0~img.cols-1
int j = rand() % img.cols;
int nl = i * img.channels();
if (img.channels() == 1){
uchar* data = img.ptr<uchar>(i);
*(data + j) = 255;
}
else if (img.channels() == 3){
Vec3b* data = img.ptr<Vec3b>(i);
(*(data + j))[0] = 255;
(*(data + j))[1] = 255;
(*(data + j))[2] = 255;
}
}
}
方法二用指针访问像素。如果是灰度图像,img.ptr < uchar>(i)得到的是i行第一个像素的地址。所以,(data + j)就可以获取到i行j列的像素了。
对于RGB图像,img.ptr< Vec3b>(i)得到的也是i行第一个像素的地址,但要注意的是这个地址对应有三个值了。( (data + j))[0]就可以获取行j列的像素B通道的值了。
- 方法三:
void salt3(Mat &img, int div){
int nl = img.rows; //行数
int nc = img.cols * img.channels();
if (img.isContinuous()){ //非边界像素
nc = nc * nl;
nl = 1;
}
for (int j = 0; j < nl; j++){
uchar* data = img.ptr<uchar>(j);
for (int i = 0; i < nc; i++){
*(data + i) = *(data + i) / div*div + div / 2;
}
}
}
方法三做的事情就是把像素RGB通道的值放在一起。当是连续的像素时,即非边界的像素,一个循环for (int j = 0; j < nc; j++)来访问所有像素的BGR值。
显然,方法三具有最高的访问效率。