图像处理中很多时候会对像素点进行操作。在OpenCV有许多方法来对像素进行遍历。
at()函数
对于单通道图像"picture1",picture1.at<uchar>(i,j)就表示在第i行第j列的像素值。
对于多通道图像如RGB图像"picture2",可以用picture2.at<Vec3b>(i,j)[c]来表示某个通道中在(i,j)位置的像素值。
1)上面的uchar、Vec3b表示图像元素的类型。
2)(i,j)当然就是指像素点的位置,表示第i行第j列。
3)[c]表示的是通道,对于RGB图像而言,c取0就是B分量;c取1就是G分量;c取2就是R分量(要注意在OpenCV中是按BGR的顺序表示的)。
在OpenCV官方文档中是这么写的:
翻译:
注意:
我们有时候回遇到这种情况
带有单个索引(i)的变量可用于访问单行或单列二维数组的元素。也就是说,如果,例如,A是一个1 x N的浮点矩阵,B是一个M x 1的整数矩阵,你可以简单地写A在<float>(k+4)处和B在<int>(2*i+1)处,而不是A在<float>(0,k+4)处和B在<int>(2*i+1,0)处。
例如:
double predictAngle = prediction.at<float>(0);
上面代码的意思就是,prediction是个单行或者单列的单通道Mat类型,prediction.at<float>(0)即为访问数组的第一个元素(可以理解为访问一个一维数组的第一个元素)
但是我发现
不是单行或者单列的Mat类型(但需要为单通道)也可以使用at<float>(n),这种情况下会默认访问矩阵第一行(row =0)的元素,以第一行来进行索引。
即double predictAngle = prediction.at<float>(4); 等价于:double predictAngle = prediction.at<float>(0,4);
/**
*Copyright (c) 2019 Young Fan.All Right Reserved.
*Author: Young Fan
*Date: 2019.05.16
*IDE: Visual Studio 2017
*Description:
*/
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("1.jpg", 0); //以单通道读入图片
int x = img.at<uchar>(118);
int y = img.at<uchar>(0,118);
cout << x << endl;
cout << y << endl;
imshow("图像", img);
waitKey();
return 0;
}
代码
下面对像素的操作,使用的是动态地址计算方式。操作像素的方式还有其他两种:C语言指针访问像素,迭代器操作像素。
单通道图像遍历:
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char** argv)
{
Mat picture(200, 200, CV_8UC1);/*创建图像picture,默认为纯黑色(即每个点的像素值为0),
大小为200 * 200,类型为CV_8UC1(是单通道图像)*/
imshow("picture", picture); //在“picture”窗口显示图像picture
//遍历picture的每个像素点,并将所有像素点的值修改为150
for (int i = 0; i < 200; i++)
{
for (int j = 0; j < 200; j++)
picture.at<uchar>(i, j) = 150;
}
imshow("dst", picture);//在“dst”窗口显示修改后的图像picture
waitKey(0);//等待用户按键
return 0;
}
运行结果:
彩色图像遍历:
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char** argv)
{
Mat picture(200, 200, CV_8UC3);//新建一个三通道彩色图像,初始默认为纯黑色
imshow("picture", picture);
//遍历picture的每个像素点,并将每个通道所有像素点的值修改为0~255中随机一个整数值
for (int i = 0; i < 200; i++)
{
for (int j = 0; j < 200; j++)
{
picture.at<Vec3b>(i, j)[0] = rand() % 255;//B通道
picture.at<Vec3b>(i, j)[1] = rand() % 255;//G通道
picture.at<Vec3b>(i, j)[2] = rand() % 255;//R通道
}
}
imshow("dst", picture);
waitKey(0);
return 0;
}
运行效果: