如果是三通道彩色图,就使用Image.at进行读取单个像素,通过 Image.at [0], Image.at[1], Image.at[2]读取每个通道的数据。访问运用 image.at(row,col) 进行访问。如果是单通道灰度图,就启用image.at进行读取。C++中协助 数组遍历 和 指针方式遍历。应用image.ptr 进行遍历。这边就是对三通道进行一个取反。


1 图像遍历与修改

C++中支持 数组遍历 和 指针方式遍历

1.1 使用数组

访问使用 image.at(row,col) 进行访问
如果是单通道灰度图,就使用image.at进行读取
如果是三通道彩色图,就使用Image.at进行读取单个像素,通过 Image.at [0], Image.at[1], Image.at[2]读取每个通道的数据

void QuickDemo::pixel_visit_demo(Mat &image)
{
int w = image.cols;
int h = image.rows;
int dimis = image.channels();
for (int row = 0; row < h; row++)
{
for (int col = 0; col < w; col++)
{
if (dimis == 1)
{
// 灰色图像 打印像素 几行几列的那个像素点
int pv = image.at<uchar>
  (row, col);
  // 修改像素点
  image.at<uchar>
    (row, col) = 255 - pv;
    }
    if (dimis == 3)
    {
    // 彩色图像 专门获取三通道的存储
    Vec3b bgr = image.at<Vec3b>
      (row, col);
      image.at<Vec3b>
        (row, col)[0] = 255 - bgr[0];
        image.at<Vec3b>
          (row, col)[1] = 255 - bgr[1];
          image.at<Vec3b>
            (row, col)[2] = 255 - bgr[2];
            }
            }
            }
            imshow("像素读写演示", image);
            }

这边就是对三通道进行一个取反
在这里插入图片描述
在这里插入图片描述

1.2 使用指针

使用image.ptr 进行遍历

for (int row = 0; row < h; row++)
{
uchar* current_row = image.ptr<uchar>
  (row);
  for (int col = 0; col < w; col++)
  {
  if (dimis == 1)
  {
  // 灰色图像 打印像素 几行几列的那个像素点
  int pv = *current_row;
  // 修改像素点
  *current_row++ = 255 - pv;
  }
  if (dimis == 3)
  {
  // 彩色图像 专门获取三通道的存储
  *current_row++ = 255 - *current_row;
  *current_row++ = 255 - *current_row;
  *current_row++ = 255 - *current_row;
  }
  }
  }

2 图像的算术运算

2.1 一般算术操作

Mat dst;
dst = image + Scalar(50, 50, 50);
imshow("加法测试");

在这里插入图片描述
同样可以使用减法,除法

Mat dst;
dst = image - Scalar(50, 50, 50);
dst = image / Scalar(2, 2, 2);
imshow("加法测试");

进行乘法时会报错,这时候需要特殊操作
使用multiply 进行乘法操作

Mat dst;
//dst = image + Scalar(50, 50, 50);
Mat m = Mat::zeros(image.size(), image.type());
multiply(image, m, dst);
imshow("加法测试");

会进行截断操作,超过255会变成255

为避免加法也会出现超过255的操作,使用C++的数据类型转换,
saturate_cast(a,b);

Mat dst = Mat::zeros(image.size(), image.type());
//dst = image + Scalar(50, 50, 50);
Mat m = Mat::zeros(image.size(), image.type());
/*multiply(image, m, dst);
imshow("加法测试");*/
m = Scalar(50, 50, 50);
int w = image.cols;
int h = image.rows;
int dimis = image.channels();
for (int row = 0; row < h; row++)
{
for (int col = 0; col < w; col++)
{
if (dimis == 1)
{
// 灰色图像 打印像素 几行几列的那个像素点
int pv = image.at<uchar>
  (row, col);
  // 修改像素点
  image.at<uchar>
    (row, col) = 255 - pv;
    }
    if (dimis == 3)
    {
    // 彩色图像 专门获取三通道的存储
    Vec3b p1 = image.at<Vec3b>
      (row, col);
      Vec3b p2 = m.at<Vec3b>
        (row, col);
        image.at<Vec3b>
          (row, col)[0] = saturate_cast<uchar>
            (p1[0] + p2[0]);
            image.at<Vec3b>
              (row, col)[1] = saturate_cast<uchar>
                (p1[1] + p2[1]);
                image.at<Vec3b>
                  (row, col)[2] = saturate_cast<uchar>
                    (p1[2] + p2[2]);
                    }
                    }
                    }

2.2 算术API

上节已经有乘法的API
multiply(第一个mat,第二个mat, 输出结果);
加法
add(image, m, dst);
减法
subtract(image , m, dst)
除法
divide(image, m, dst)

multiply(image, m, dst);
add(image, m, dst);
subtract(image, m, dst);
divide(image, m, dst);
posted @ 2025-07-24 14:52  wzzkaifa  阅读(4)  评论(0)    收藏  举报