点运算
像素点的基本操作和卷积
图像处理最本质的操作是对每个像素点的像素值进行处理。在这里我们介绍一下如何使用OpenCv访问图像中的像素点。(这里默认使用的图像为Mat类型,RGB三通道的图像通道)
常见的访问方式如下:
利用指针进行访问
通过调用函数Mat::ptr(i)来得到第i行的首地址,然后在行内访问像素
for(int i=0;i<Row;i++)
{
for(int j=0;j<Col;j++)
{
for(int c=0;c<3;c++)
{
Scr.ptr<Vec3b>(i)(j)[c]=0;//Scr.at<ushort>(i,j)=0;单通道读取
}
}
}
上面的Vec3b指的是三通道uchar类型的数据。i、j表示像素点在图像中的位置,而[c]表示通道编号,因为是三通道数据,所以[c]表示RGB通道(在OpenCv中图像通道为BGR,编号为0,1,2),而三通道float类型的矩阵可以使用。
动态访问
动态访问是比较慢的读取操作,但是比较容易进行理解。另外这样做可以在OpenC
v内部安全检查,以防止访问越界。使用at()函数得到像素,Mat::at(i,j)为应该像素点的像素值数组,是一个大小为3的数组,值从0~2分别存放了B,G,R三个通道的灰度值。
for(int i=0;i<Row;i++)
for(int j=0;j<Col;j++)
for(int c=0;c<3;c++)
{
Scr.ptr<Vec3b>(i)(j)[c]=0;
}
像素点亮度操作
对图像中每个元素加上(或者减去)一个常数。(saturate_cast()函数的作用是当运算完成后,结果为负数则转为0,结果超出255,就转换为255)
for(int i=0;i<Row;i++)
for(int j=0;j<Col;j++)
for(int c=0;c<3;c++>)
{
Scr.at<Vec3b>(i,j)[c]=saturate_cast<uchar>(Scr.at<Vec3b>(i,j)[c]+5);
}
使用迭代器遍历图像
cv::Mat同样有标准模板库(STL),可以使用迭代器访问数据。
用迭代器来遍历图像像素,可简化过程降低出错的机会,比较安全,不过效率较低;如果想避免修改输入图像实例cv::Mat,可采用const_iterator。iterator有两种调用方法,cv::MatIterator_cv::Vec3bit;cv::Mat_cv::Vec3b::iterator it;中间cv::Vec3b是因为图像是彩色图像,3通道,cv::Vec3b可以代表一个像素。
cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();
for (; it != itend; ++it)
{
(*it)[0] = (*it)[0] / div*div + div / 2;
(*it)[1] = (*it)[1] / div*div + div / 2;
(*it)[2] = (*it)[2] / div*div + div / 2;
}
像素点亮度操作
对图像每个像素点点都加上(或者减去)一个常数。设图像亮度为v,b是亮度常数,公式为v=v+b。(saturate_cast的作用是运算完成后如果结果为负数则转换为0,结果超出则转换为255)
for(int i=0;i<Row;i++)
for(int j=0;j<Col;j++)
for(int c=0;c<3;c++)
Scr.at<Vec3b>(i,j)[c]=saturate_cast<uchar>(Scr.at<Vec3b>(i,j)[c]+5);