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

在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;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值