Opencv学习笔记之二:操作像素

来源:互联网 发布:搜索优化 编辑:程序博客网 时间:2024/05/15 23:32

在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;  }  
0 0