【opencv学习之十六】像素操作和Reduce Color的例子

访问像素的方法很多这里举三个经典例子,第一个是椒盐噪声,就是在图像上随机将其中的某些像素至为白色,看起来就像撒了盐;

代码如下:

1.访问像素并修改
void salt()
{
    Mat image;
    int n=10000;
    image = cv::imread("D:/2.jpg");
    int i, j;
    for (int k = 0; k < n; k++) {
        i = std::rand() % image.cols;//c++rand()函数生成随机整数,最大值image.cols;
        j = std::rand() % image.rows;//c++rand()函数生成随机整数,最大值image.cols;
        if (image.type() == CV_8UC1)     // CV_8UC1为灰度图像
        {
            image.at<uchar>(j, i) = 255;//这个方法是将这个点变为白色;at方法为一个模板函数,调用时候指定元素类型,uchar为0-255;
        }
        else if (image.type() == CV_8UC3)  // CV_8UC3为彩色图像(三通道)
        {
            //  Vec3b---表示每一个Vec3b对象中,可以存储3个char(字符型)数据,比如可以用这样的对象,去存储RGB图像中的一个像素点
            //Opencv中图像三原色在内存中的排列顺序为B-G-R
            image.at<cv::Vec3b>(j, i)[0] = 255;//访问第一通道B
            image.at<cv::Vec3b>(j, i)[1] = 255;//访问第二通道G
            image.at<cv::Vec3b>(j, i)[2] = 255;//访问第三通道R
        }
    }
    cv::imshow("Image", image);
    cv::waitKey(0);
}
效果如下:


下面是集中减少色彩的操作,比如原来的图像是是256中颜色,我希望将它变成64种颜色,那我只需要将原来的颜色除以4(整除)以后再乘以4就可以了;
1、直接访问at操作:

void colorReduce1()//mat,at操作方法,直接访问像素点
{
    Mat image;
    image = cv::imread("D:/2.jpg");
    int div = 64;
    int rows =  image.rows;
    int cols = image.cols;
    for(int i = 0;i < rows;i++)
    {
        for(int j = 0;j < cols;j++)
        {
            image.at<Vec3b>(i,j)[0] = image.at<Vec3b>(i,j)[0]/div*div + div/2;
            image.at<Vec3b>(i,j)[1] = image.at<Vec3b>(i,j)[1]/div*div + div/2;
            image.at<Vec3b>(i,j)[2] = image.at<Vec3b>(i,j)[2]/div*div + div/2;
        }
    }
    cv::imshow("Image", image);
    cv::waitKey(0);
}

2、逐行操作:

//逐行读取
/// 经典的Reduce Color的例子,即对图像中的像素表达进行量化。
/// 如常见的RGB24图像有256×256×256中颜色,
/// 通过Reduce Color将每个通道的像素减少8倍至256/8=32种,
/// 则图像只有32×32×32种颜色。假设量化减少的倍数是N,
/// 则代码实现时就是简单的value/N*N,通常我们会再加上N/2以得到相邻的N的倍数的中间值,
/// 最后图像被量化为(256/N)×(256/N)×(256/N)种颜色。
void colorReduce2()
{
    Mat image;
    image = cv::imread("D:/2.jpg");
    int div = 64;
    int nl = image.rows; // 行数
    int nc = image.cols * image.channels();  // 每行的元素数量
    for (int j = 0; j < nl; j++)//遍历行数
    {
        uchar* data = image.ptr<uchar>(j);//cv::Mat类提供ptr函数,可以直接访问图像中任一行的地址
        for (int i = 0; i < nc; i++)//遍历一行的元素
        {
            data[i] = data[i] / div*div + div / 2; //修改像素值
            //*data = *data / div*div + div2; data++;  //另一种等价的做法, 即利用指针运算从一列移到下一列
        }
    }
    cv::imshow("Image", image);
    cv::waitKey(0);
}
3、容器操作:

//mat操作,容器操作
void colorReduce3()
{
    Mat image;
    image = cv::imread("D:/2.jpg");
    int div = 64;
    cv::Mat_<cv::Vec3b>::iterator it;//模板子类,因此迭代器返回cv::Vec3b实例
    it = image.begin<cv::Vec3b>();//begin起始位
    cv::Mat_<cv::Vec3b>::iterator itend =image.end<cv::Vec3b>();// end结束位置
    for (; it != itend; ++it)
    {
        (*it)[0] = (*it)[0] / div*div + div / 2;//用[ ]访问每个颜色通道的元素,返回cv::Vec3b
        (*it)[1] = (*it)[1] / div*div + div / 2;
        (*it)[2] = (*it)[2] / div*div + div / 2;
    }
    cv::imshow("Image", image);
    cv::waitKey(0);
}


4、指针操作:

//指针方法
void colorReduce4()
{
    Mat image;
    image = cv::imread("D:/2.jpg");
    int div = 64;
    int rows = image.rows;
    int cols = image.cols*image.channels();
    for(int i = 0;i < rows;i++)
    {
        uchar* data = image.ptr<uchar>(i);
        uchar* dataout =image.ptr<uchar>(i);
        for(int j = 0;j < cols;j++)
        {
            dataout[j] = dataout[j]/div*div + div/2;
        }
    }
    cv::imshow("Image", image);
    cv::waitKey(0);
}
所有操作效果图一样,如下:



原图如下:



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值