在OpenCV中,提供了种访问每个像素的方法:使用at方法、使用迭代器、使用指针。以下将介绍几种方法的使用。
例:椒盐噪声
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
/*实现原理:
利用rows与cols可得到图像的行数与列数
Mat中的at(int y,int x)方法可以访问任意元素
at方法被实现成一个模板方法,在调用时需指定图像元素的类型
image.at<uchar>(j,i)=255;
彩色通道对应了R,G,B三种通道,因此彩色图像返回一个包含3个8位的数值。
image.at<Vec3b>(j,i)[channel]=value;chnannel指定通道的任意一个。依次是b(0),g(1),r(2)
*/
void salt(Mat image,int n){
//用它在图像中添加椒盐噪声,这里我们随机选择一些像素点,将其置成白色。
//椒盐噪声:随机选择一些像素点,将其颜色替换成白色和黑色。因为通信出错时,部分像素值在传输过程中,丢失,就会发生这种噪音。
int i,j;
for (int k=0;k<n;k++)
{
//随机数生成器
i=rand()%image.cols;//随机生成的在列范围之内
j=rand()%image.rows;//随机生成的在行范围之内
if(image.type()==CV_8UC1){//灰度图像
image.at<uchar>(j,i)=255;//at<类型>(j,i)//行列,访问像素
//用at<uchar>(j,i)或at<Vec3b>(j,i)[channels]访问单通道或三通道数据
}else if(image.type()==CV_8UC3){//彩色图像
image.at<Vec3b>(j,i)[0]=255;//b,3b:代表二进制数
image.at<Vec3b>(j,i)[1]=255;//g
image.at<Vec3b>(j,i)[2]=255;//r
//同理还有<Vec2b>,<Vec4b>,<Vec2f>浮点型。
}
}
}
int main(){
//打开图像
Mat image=imread("C:\\Users\\liufeng\\Desktop\\opencv图像库\\1.jpg");
//调用函数以添加噪声
salt(image,2000);//图像没必要采取引用 传递
namedWindow("image");
imshow("image",image);
waitKey(0);
return 0;
}
下面分别用三种方法来实现减色函数;
(1)at方法
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
outputImage = inputImage.clone();
int rows = outputImage.rows;
int cols = outputImage.cols;
for(int i = 0;i < rows;i++)
{
for(int j = 0;j < cols;j++)
{ //假设三通道
outputImage.at<Vec3b>(i,j)[0] = outputImage.at<Vec3b>(i,j)[0]/div*div + div/2;
outputImage.at<Vec3b>(i,j)[1] = outputImage.at<Vec3b>(i,j)[1]/div*div + div/2;
outputImage.at<Vec3b>(i,j)[2] = outputImage.at<Vec3b>(i,j)[2]/div*div + div/2;
}
}
}
(2).指针方式
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
outputImage = inputImage.clone();
int rows = outputImage.rows;
int cols = outputImage.cols*outputImage.channels();
//将通道数乘了进去
for(int i = 0;i < rows;i++)
{
uchar* data = inputImage.ptr<uchar>(i);
uchar* dataout = outputImage.ptr<uchar>(i);
for(int j = 0;j < cols;j++)
{
dataout[j] = dataout[j]/div*div + div/2;
}
}
}
(3)迭代器
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
outputImage = inputImage.clone();
//模板必须指明数据类型
Mat_<Vec3b>::iterator it = inputImage.begin<Vec3b>();
Mat_<Vec3b>::iterator itend = inputImage.end<Vec3b>();
for(;it != itend;it++,itout++)
{
(*itout)[0] = (*it)[0]/div*div + div/2;
(*itout)[1] = (*it)[1]/div*div + div/2;
(*itout)[2] = (*it)[2]/div*div + div/2;
}
}
减色函数:data[i]=data[i]/div*div+div/2;
at访问:outputImage.at(i,j)[channels] = outputImage.at(i,j)[channels]/div*div + div/2;
指针访问: uchar* dataout = outputImage.ptr(i); //ptr是获得行地址。
for(int j = 0;j < cols;j++)
{
dataout[j] = dataout[j]/div*div + div/2;
}
迭代器访问:
Mat_::iterator it = inputImage.begin();
Mat_::iterator itend = inputImage.end();
for(;it != itend;it++,itout++)
{
(*itout)[0] = (*it)[0]/div*div + div/2;
(*itout)[1] = (*it)[1]/div*div + div/2;
(*itout)[2] = (*it)[2]/div*div + div/2;
}