欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-01 08:45:51
...

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

代码如下:

////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);
}
效果如下:

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

下面是集中减少色彩的操作,比如原来的图像是是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);
}
所有操作效果图一样,如下:

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

原图如下:

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