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

来源:互联网 发布:ug10编程免费视频教程 编辑:程序博客网 时间:2024/06/06 11:08

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

代码如下:

////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 0
原创粉丝点击