OpenCV 像素的读取与操作

像素读取和操作

1. 利用cv::Matat函数,直接访问具体地址

void get_setImagePixel(char *imagePath, int x, int y)

{

    //  Mat image = imread(imagePath , 0);

    Mat image = imread(imagePath, 1);

    //得宽高

    int w = image.cols;

    int h = image.rows;


    int channels = image.channels();

    if (x < w && y < h)

    {

        //灰度图,像素为单通道

        if (channels == 1)

        {

            int pixel = image.at<uchar>(x, y);

            cout << "灰度图像,处的灰度值为" << pixel << endl;

        }

        else

        {

            //通过实验,彩色图像的默认存储是bgr, 且存储的格式如下


            //读取

            int b = image.at<Vec3b>(x, y)[0]; // b = image.at<uchar>(x,y*3);

            cout << b << endl;

            int g = image.at<Vec3b>(x, y)[1]; //g = image.at<uchar>(x, y * 3 + 1);

            cout << g << endl;

            int r = image.at<Vec3b>(x, y)[2]; //r = image.at<uchar>(x, y * 3 + 1);

            cout << r << endl;


            //设置像素值

            image.at<Vec3b>(x, y)[0] = 255;

            image.at<Vec3b>(x, y)[1] = 255;

            image.at<Vec3b>(x, y)[2] = 255;

        }

    }

    imshow("cc", image);

}

 

2. 利用Mat prt 函数:行首地址访问

void get_setImagePixel2(char *imagePath, int x, int y)

{

    Mat image = imread(imagePath, 1);

    //得宽高

    int w = image.cols;

    int h = image.rows;

    int channels = image.channels();

    //如果图像连续 ,可以将数据转化为1维数组,提高访问效率,但对少量像素访问就没必要

    //if (image.isContinuous())

    //{

    //  //reshape函数用于改变矩阵维度 

    //  //图像行数为1,列数为原先的行数乘上列数 

    //  image.reshape(1, image.cols*image.rows);

    //}


    //获得第y行的首地址

    uchar *data = image.ptr<uchar>(y);

    int position = x*channels;

    if (channels == 1)

    {

        int pixel = data[position];

        cout << "灰度图像,处的灰度值为" << pixel << endl;

    }

    else

    {

        //通过实验,彩色图像的默认存储是bgr, 且存储的格式如下


        //读取

        int b = data[position];

        cout << b << endl;

        int g = data[position+1];

        cout << g << endl;

        int r = data[position+2];

        cout << r << endl;


        //设置像素值

        data[position] = 255;

        data[position+1] = 255;

        data[position+2] = 255;

    }

    imshow("cc", image);

}

3. 利用迭代器遍历图像
 

void get_setImagePixel3(char *imagePath, int x, int y)

{

    Mat image = imread(imagePath, 1);

    //得宽高

    int w = image.cols;

    int h = image.rows;

    int channels = image.channels();



    if (channels == 1)

    {

        //得到初始位置的迭代器 

        Mat_<uchar>::iterator it = image.begin<uchar>();

        //得到终止位置的迭代器 

        Mat_<uchar>::iterator itend = image.end<uchar>();

        int pixel = *(it + y * w + x);

        cout << "灰度图像,处的灰度值为" << pixel << endl;

    }

    else

    {

        //得到初始位置的迭代器 

        Mat_<Vec3b>::iterator it = image.begin<Vec3b>();

        //得到终止位置的迭代器 

        Mat_<Vec3b>::iterator itend = image.end<Vec3b>();

        //读取

        it = it + y * w + x;

        int b = (*it)[0];

        cout << b << endl;

        int g = (*it)[1];

        cout << g << endl;

        int r = (*it)[2];

        cout << r << endl;



        //设置像素值

            (*it)[0] = 255;

            (*it)[1] = 255;

            (*it)[2] = 255;


    }

    imshow("cc", image);


}

若是大量访问数据和更改数据时用第二种方式效率高。

Node: 在修改像素时候,最好先用变量存储,设定好了再赋值给Mat成员对象,如data,因为如果直接进行操作时,当一个分量值大于255时,向前进1的原则,则会修改前面像素的值,如下:

id colorReduce(cv::Mat&image, int div)

{

    int nl = image.rows; //图像的行数 

    //图像每行的像素数 

    int nc = image.cols * image.channels();

    for (int j = 0; j<nl; j++)

    {

        //得到第j行的首地址 

        uchar* data = image.ptr<uchar>(j);

        //遍历每行的像素 

        for (int i = 0; i<nc; i++)

        {

            //printf("%d    ", data[i]);

            //data[i] = data[i] / div*div + 6;// 这里需要用c来存储,因为如果大于255时会向前进1,则影响前面的像素,data[i] 会自己变得小255

            int c = data[i] / div*div + 100;       

            data[i] =  c > 255 ? 255 : c;    //将每个像素值都变为div的倍数,即将颜色数缩减了div倍                        


        }

    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值