OpenCV 图像像素的读写操作

一、知识点
**1、**在OpenCV中,一切图像皆Mat。

**2、**对图像像素的读写操作,就是对Mat元素的遍历与访问。

3、 对Mat使用数组方式遍历与访问。

(1)、函数声明:

cpp 复制代码
      template<typename _Tp> inline
      _Tp & Mat::at(int i0, int i1)

(2)、参数说明:

i0: 行索引。 从0开始,应小于image.rows。

i1: 列索引。 从0开始,应小于image.cols。

_Tp: 函数模板的类型参数,表示一个像素的数据类型。

(3)、返回i0行i1列的元素引用,返回值是_Tp &,说明对返回值可读可写,可写会影响原始数据。

(4)、灰度图像的遍历与访问举例:

cpp 复制代码
      for (int row = 0; row < h; row++)
      {
          for (int col = 0; col < w; col++)
          {
                if (c == 1)
                {
                      //读
                      int pv = image.at<uchar>(row, col);
                      //写
                      image.at<uchar>(row, col) = 255 - pv;
                }
          }
      }

(5)、彩色图像的遍历与访问举例:

cpp 复制代码
      for (int row = 0; row < h; row++)
      {
            for (int col = 0; col < w; col++)
            {
                  if (c == 3)
                  {
                        //读
                        cv::Vec3b bgr = image.at<cv::Vec3b>(row, col);
                        //写
                        image.at<cv::Vec3b>(row, col)[0] = 255 - bgr[0];
                        image.at<cv::Vec3b>(row, col)[1] = 255 - bgr[1];
                        image.at<cv::Vec3b>(row, col)[2] = 255 - bgr[2];
                  }
            }
      }

4、 对Mat使用指针方式遍历与访问。

(1)、函数声明:

cpp 复制代码
      template<typename _Tp> inline
      _Tp * Mat::ptr(int y)

(2)、参数说明:

y: 行索引。 从0开始,应小于image.rows。

_Tp: 函数模板的类型参数,表示返回的指针指向的数据类型,通常是一个像素的数据类型。

(3)、返回y行首个_Tp类型数据的地址,返回值是_Tp *,说明对返回值可读可写,可写会影响原始数据。

(4)、灰度图像的遍历与访问举例:

cpp 复制代码
      for (int row = 0; row < h; row++)
      {
          //返回row行首个元素的地址
          uchar * cur_row = image.ptr<uchar>(row);

          for (int col = 0; col < w; col++)
          {
              if (c == 1)
              {
                    int pv = *cur_row;
                    *cur_row = 255 - pv;
                    cur_row++;
              }
          }
      }

(5)、彩色图像的遍历与访问举例:

cpp 复制代码
      for (int row = 0; row < h; row++)
      {
          //返回row行首个元素的首个字节地址
          uchar * cur_row = image.ptr<uchar>(row);

          for (int col = 0; col < w; col++)
          {
              if (c == 3)
              {
                  int pv1 = *cur_row;
                  *cur_row = 255 - pv1;
                  cur_row++;
                  
                  int pv2 = *cur_row;
                  *cur_row = 255 - pv2;
                  cur_row++;
                  
                  int pv3 = *cur_row;
                  *cur_row = 255 - pv3;
                  cur_row++;
              }
          }
      }

5、 对Mat使用指针方式遍历与访问2。

(1)、函数声明:

cpp 复制代码
      template<typename _Tp> inline
      _Tp * Mat::ptr(int i0, int i1)

(2)、参数说明:

i0: 行索引。 从0开始,应小于image.rows。

i1: 列索引。 从0开始,应小于image.cols。

_Tp: 函数模板的类型参数,表示一个像素的数据类型。

(3)、返回i0行i1列的元素地址,返回值是_Tp *,说明对返回值可读可写,可写会影响原始数据。

(4)、灰度图像的遍历与访问举例:

cpp 复制代码
      for (int row = 0; row < h; row++)
      {
            for (int col = 0; col < w; col++)
            {
                  if (c == 1)
                  {
                        uchar * pv = image.ptr<uchar>(row, col);
                        *pv = 255 - *pv;
                  }
            }
      }

(5)、彩色图像的遍历与访问举例:

cpp 复制代码
      for (int row = 0; row < h; row++)
      {
            for (int col = 0; col < w; col++)
            {
                  if (c == 3)
                  {
                        cv::Vec3b * pv = image.ptr<cv::Vec3b>(row, col);
                        *pv = cv::Vec3b(255 - (*pv)[0], 255 - (*pv)[1], 255 - (*pv)[2]);
                  }
            }
      }

二、示例代码:

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>


void visit_by_array(cv::Mat & image)
{
    int w = image.cols;
    int h = image.rows;
    int c = image.channels();

    for (int row = 0; row < h; row++)
    {
        for (int col = 0; col < w; col++)
        {
            //灰度图像
            if (c == 1)
            {
                //读
                int pv = image.at<uchar>(row, col);
                //写
                image.at<uchar>(row, col) = 255 - pv;
            }
            //彩色图像
            else if (c == 3)
            {
                //读
                cv::Vec3b bgr = image.at<cv::Vec3b>(row, col);
                //写
                image.at<cv::Vec3b>(row, col)[0] = 255 - bgr[0];
                image.at<cv::Vec3b>(row, col)[1] = 255 - bgr[1];
                image.at<cv::Vec3b>(row, col)[2] = 255 - bgr[2];
            }
        }
    }
}


void visit_by_pointer(cv::Mat & image)
{
    int w = image.cols;
    int h = image.rows;
    int c = image.channels();
     
    for (int row = 0; row < h; row++)
    {
        uchar * cur_row = image.ptr<uchar>(row);

        for (int col = 0; col < w; col++)
        {
            //灰度图像
            if (c == 1)
            {
                //读
                int pv = *cur_row;
                //写
                *cur_row = 255 - pv;
                cur_row++;
            }
            //彩色图像
            else if (c == 3)
            {
                //读
                int pv1 = *cur_row;
                //写
                *cur_row = 255 - pv1;
                cur_row++;

                //读
                int pv2 = *cur_row;
                //写
                *cur_row = 255 - pv2;
                cur_row++;

                //读
                int pv3 = *cur_row;
                //写
                *cur_row = 255 - pv3;
                cur_row++;
            }
        }
    }
}


void visit_by_pointer2(cv::Mat & image)
{
    int w = image.cols;
    int h = image.rows;
    int c = image.channels();

    for (int row = 0; row < h; row++)
    {
        for (int col = 0; col < w; col++)
        {
            if (c == 1)
            {
                uchar * pv = image.ptr<uchar>(row, col);
                *pv = 255 - *pv;
            }
            else if (c == 3)
            {
                cv::Vec3b * pv = image.ptr<cv::Vec3b>(row, col);
                *pv = cv::Vec3b(255 - (*pv)[0], 255 - (*pv)[1], 255 - (*pv)[2]);
            }
        }
    }
}


int main()
{
    //数组方式访问灰度图像
    cv::Mat m1 = cv::imread("../images/1.png", cv::IMREAD_GRAYSCALE);
    if (m1.empty())
    {
        std::cout << "load m1 error..." << std::endl;
        return -1;
    }
    cv::imshow("数组方式访问前 m1", m1);
    visit_by_array(m1);
    cv::imshow("数组方式访问后 m1", m1);

    //数组方式访问彩色图像
    cv::Mat m2 = cv::imread("../images/1.png", cv::IMREAD_COLOR_BGR);
    if (m2.empty())
    {
        std::cout << "load m2 error..." << std::endl;
        return -1;
    }
    cv::imshow("数组方式访问前 m2", m2);
    visit_by_array(m2);
    cv::imshow("数组方式访问后 m2", m2);

    //指针方式1访问灰度图像
    cv::Mat m3 = cv::imread("../images/2.png", cv::IMREAD_GRAYSCALE);
    if (m3.empty())
    {
        std::cout << "load m3 error..." << std::endl;
        return -1;
    }
    cv::imshow("指针方式1访问前 m3", m3);
    visit_by_pointer(m3);
    cv::imshow("指针方式1访问后 m3", m3);

    //指针方式1访问彩色图像
    cv::Mat m4 = cv::imread("../images/2.png", cv::IMREAD_COLOR_BGR);
    if (m4.empty())
    {
        std::cout << "load m4 error..." << std::endl;
        return -1;
    }
    cv::imshow("指针方式1访问前 m4", m4);
    visit_by_pointer(m4);
    cv::imshow("指针方式1访问后 m4", m4);

    //指针方式2访问灰度图像
    cv::Mat m5 = cv::imread("../images/3.png", cv::IMREAD_GRAYSCALE);
    if (m5.empty())
    {
        std::cout << "load m5 error..." << std::endl;
        return -1;
    }
    cv::imshow("指针方式2访问前 m5", m5);
    visit_by_pointer2(m5);
    cv::imshow("指针方式2访问后 m5", m5);

    //指针方式2访问彩色图像
    cv::Mat m6 = cv::imread("../images/3.png", cv::IMREAD_COLOR_BGR);
    if (m6.empty())
    {
        std::cout << "load m6 error..." << std::endl;
        return -1;
    }
    cv::imshow("指针方式2访问前 m6", m6);
    visit_by_pointer2(m6);
    cv::imshow("指针方式2访问后 m6", m6);

    cv::waitKey(0);
    return 0;
}
相关推荐
lxmyzzs1 小时前
【图像算法 - 21】慧眼识虫:基于深度学习与OpenCV的农田害虫智能识别系统
人工智能·深度学习·opencv·算法·yolo·目标检测·计算机视觉
Gloria_niki1 小时前
机器学习之K 均值聚类算法
人工智能·机器学习
AI人工智能+1 小时前
表格识别技术:通过图像处理与深度学习,将非结构化表格转化为可编辑结构化数据,推动智能化发展
人工智能·深度学习·ocr·表格识别
深圳多奥智能一卡(码、脸)通系统1 小时前
智能二维码QR\刷IC卡\人脸AI识别梯控系统功能设计需基于模块化架构,整合物联网、生物识别、权限控制等技术,以下是多奥分层次的系统设计框架
人工智能·门禁·电梯门禁·二维码梯控·梯控·电梯
批量小王子1 小时前
2025-08-19利用opencv检测图片中文字及图片的坐标
人工智能·opencv·计算机视觉
没有梦想的咸鱼185-1037-16632 小时前
SWMM排水管网水力、水质建模及在海绵与水环境中的应用
数据仓库·人工智能·数据挖掘·数据分析
即兴小索奇2 小时前
【无标题】
人工智能·ai·商业·ai商业洞察·即兴小索奇
国际学术会议-杨老师2 小时前
2025年计算机视觉与图像国际会议(ICCVI 2025)
人工智能·计算机视觉
欧阳小猜3 小时前
深度学习②【优化算法(重点!)、数据获取与模型训练全解析】
人工智能·深度学习·算法
fsnine3 小时前
深度学习——神经网络
人工智能·深度学习·神经网络