【OpenCV】之图像像素访问方法

任何图像处理算法,都是从操作图像中的每个像素开始的。
图像的存储:
1.单通道图像
这里写图片描述
2.多通道图像
这里写图片描述

【方法1】指针访问像素: 访问速度最快
用指针访问像素是C语言中操作符[ ]。
图像中每行像素的个数: 每行像素数=列数 X 通道数
Mat类提供了ptr函数可得到图像任意行的首地址。
// 获取i行的首地址
uchar *data = image.ptr<uchar>(i);
//--------------【colorReduce()函数】---------------//
//  Description:通过指针实现颜色空间缩减函数
//-------------------------------------------------
void colorReduce(Mat &srcImg, Mat &dstImg, int div)
{
    // 设置参数
    dstImg = srcImg.clone(); // 设置目标图像与源图像一样
    int rowNum = dstImg.rows; // 行数
    int colNum = dstImg.cols * dstImg.channels(); // 每行像素数 = 列数 x 通道数

    // 双重循环,遍历所有的像素值
    for (int i = 0; i < rowNum; i++) // 行循环
    {
        uchar *data = dstImg.ptr<uchar>(i); // 获取第i行的首地址
        for (int j = 0; j < colNum; j++) // 列循环
        {
            // 开始处理每个像素
            data[j] = data[j] / div * div + div / 2;
        } // 处理完一行,进行下一行像素处理
    }
}
【方法2】 迭代器操作像素
在迭代法中,我们只需获取图像矩阵的begin和end,然后增加迭代直至从begin到end。将*操作符添加在迭代指针前,即可访问当前指向的内容。
相比用指针直接访问像素可能出现越界问题,迭代器绝对是非常安全的方法。
该方法与STL库的用法类似
//--------------【colorReduce()函数】---------------//
//  Description:通过迭代器实现颜色空间缩减函数
//-------------------------------------------------
void colorReduce(Mat &srcImg, Mat &dstImg, int div)
{
    // 设置参数
    dstImg = srcImg.clone(); // 设置目标图像与源图像一样
    // 获取迭代器
    Mat_<Vec3b>::iterator it = dstImg.begin<Vec3b>(); // 初始位置的迭代器
    Mat_<Vec3b>::iterator itEnd = dstImg.end<Vec3b>(); // 终止位置的迭代器

    // 存取彩色图像像素
    for (; it != itEnd; it++) // 行循环
    {
        // 开始处理每个像素
        (*it)[0] = (*it)[0] / div * div + div / 2;
        (*it)[1] = (*it)[1] / div * div + div / 2;
        (*it)[2] = (*it)[2] / div * div + div / 2;
    }
}

注意:(*it)[0]代表蓝色通道像素值,(*it)[1]代表绿色通道像素值,(*it)[2]代表红色通道像素值。在OpenCV中,RGB存储是顺序是BGR

【方法3】 动态地址访问
该方法较直观,但耗时最长。
//--------------【colorReduce()函数】---------------//
//  Description:通过动态地址实现颜色空间缩减函数
//-------------------------------------------------
void colorReduce(Mat &srcImg, Mat &dstImg, int div)
{
    // 设置参数
    dstImg = srcImg.clone(); // 设置目标图像与源图像一样
    int rowNum = dstImg.rows; // 行数
    int colNum = dstImg.cols ; // 列数

    // 存取彩色图像像素
    for (int i = 0; i < rowNum; i++) // 行循环
    {
        for (int j = 0; j < colNum; j++) // 列循环
        {
            // 开始处理每个像素
            dstImg.at<Vec3b>(i,j)[0] = dstImg.at<Vec3b>(i,j)[0] / div * div + div / 2; // 蓝色通道
            dstImg.at<Vec3b>(i,j)[1] = dstImg.at<Vec3b>(i,j)[1] / div * div + div / 2; // 绿色通道
            dstImg.at<Vec3b>(i,j)[2] = dstImg.at<Vec3b>(i,j)[2] / div * div + div / 2; // 红色通道
        } // 处理完
    }
}

Mat 类中的cols和rows给出了图像的宽和高。而成员函数at(int y, int x)可用来存取图像元素,但必须在编译期知道图像的数据类型。
在OpenCV将彩色图像的类型的向量定义为Vec3b,即由三个unsigned char 组成的向量。

image.at<Vec3b>(i, j)[channel] = value;

【摘引:】

  1. 《OpenCV3编程入门》
  2. https://www.cnblogs.com/skyfsm/p/7082914.html

猜你喜欢

转载自blog.csdn.net/y363703390/article/details/79445987