opencv操作像素

1、访问元素
使用Mat的at(int x int y)可以访问指定位置的元素。
如:

image.at<uchar>(j,i)=255;//将j行i列的像素点的值设为255

2、用指针扫描图像
使用指针访问图像的每个像素,将其值设为原来的1/8

void colorReduce(cv::Mat image,int div=64)
{
   int rows=image.rows;
   int num_per_rows=image.cols*image.channels();//每行元素的数量
   for(int j=0;j<rows;i++)
    {
      uchar* data=image.ptr<uchar>(j);//uchar指向第j行的地址
      for(int i=0;i<num_per_row;i++)
          data[i]=data[i]/div*div+div/2;//处理每个像素
     }
}

3、使用迭代器扫描图像
要得到cv::Mat实例的迭代器,先要创建一个cv::MatIterator_的对象;
如:

cv::MatIterator_<cv::Vec3b> it;

或者是:

cv::Mat_<cv::Vec3b>::iterator it;

比如获取一个图像的开始和结尾的迭代器:

cv::Mat_<cv::Vec3b>::iterator begin=image.begin<cv::Vec3b>();//开始位置
cv::Mat_<cv::Vec3b>::iterator end=image.end<cv::Vec3b>();//结尾位置
for(;begin!=end;begin++)
{
    (*begin)[0]=(*begin)[0]+10;
    (*begin)[1]=(*begin)[1]+15;
    (*begin)[2]=(*begin)[2]+20;
}

常量迭代器定义:

cv::MatConstIterator_<cv::Vec3b> it;
//或者
cv::Mat_<cv::Vec3b>::const_iterator it;

4、扫描并访问相邻像素
在图像处理中计算像素值时,经常需要用它的相邻像素值。如果相邻像素在上一行火下一行,就需要同事扫描图像的多行。
以图像锐化为例子;在图像处理领域,如果从图像中减去拉普拉斯算子部分,图像的边缘就会放大,因而图像会变得尖锐;
锐化方法:
sharpened_pixel=5*current-left-right-up-down;
但是第一行,最后一行,第一列,最后一列的像素值是无法计算的。

void sharpen(const cv::Mat& iamge,cv::Mat& result)
{
   result.create(image.size(),image.type());//分配图像空间
   int nchannels=image.channels();//读取通道数
   for(int j=1;j<image.rows-1;j++)//处理除了第一行和最后一行的所有行
   {
      const uchar* previous=image.ptr<const uchar>(j-i);//上一行
      const uchar* current=image.ptr<const uchar>(j);//当前行
      const uchar* next=image.ptr<const uchar>(j+i);//下一行
      uchar* output=result.ptr<uchar>(j);//输出行
      for(int i=nchannels;i<(image.cols-1)*nchannels;i++)
       {
           *output++=cv::saturate_cast<uchar>(5*current[i]-current[i-nchannels]-current[i+nchannels]-previous[i]-next[i]);
        }
   }
//未处理的像素设置为0
   result.row(0).setTo(cv::Scalar(0));
   result.row(result.rows-1).setTo(cv::Scalar(0));
   result.col(0).setTo(cv::Scalar(0));
   result.col(result.rows-1).setTo(cv::Scalar(0)); 
}

cv::saturate_cast函数将结果调整到8位无符号整数范围内,就是将大于255的设为255,小于0的设为0;
setTo方法可以对矩阵中的所有元素赋值。

在对像素领域进行计算时,通常用一个核心矩阵来表示,这个矩阵展示了为得到预期的结果,如何将计算相关的像素组合起来。
cv::filter2D函数只需要一个内核,调用函数并传入图像和内核,即可返回滤波后的图像;

void sharpen2D(const cv::Mat& image,cv::Mat& result)
{
    //构造内核
    cv::Mat kernel(3,3,CV_32F,cv::Scalar(0));
    //对内核赋值
    kernel.at<float>(1,1)=5.0;
    kernel.at<float>(0,1)=-1.0;
    kernel.at<float>(2,1)=-1.0;
    kernel.at<float>(1,0)=-1.0;
    kernel.at<float>(1,2)=-1.0;
   //对图像滤波
   cv::filter2D(image,result,image.depth(),kernel);
}

5、图像运算

//c[i]=a[i]+b[i];
cv::add(imageA,imageB,resultC);
//c[i]=a[i]+k;
cv::add(imageA,cv::Scalar(k),resultC);
//c[i]=k1*a[i]+k2*b[i]+k3;
cv::addWeighted(imageA,k1,image2,k2,k3,resultC);

6、图像重映射
图像重映射的过程不会修改图像的值,而是把每个像素的位置重新映射到新的位置。

void wave(const cv::Mat& iamge,cv::Mat& result)
{
   cv::Mat srcX(image.rows,image.cols,CV_32F);
   cv::Mat srcY(image.rows,image.cols,CV_32F);
   for(int i=0;i<image.rows;i++)
     for(int j=0;j<image.clos;j++)
      {
         srcX.at<float>(i,j)=j;
         srcY.at<float>(i,j)=i+5*sin(j/10.0);
      }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值