OpenCV入门(9):基本操作之图像像素值、属性、颜色空间转换、数值类型转换

一、访问和修改像素值

图像是由像素组成的矩阵,每个像素都有一个或多个值,表示颜色或灰度。

  • 在灰度图像中,每个像素只有一个值,表示灰度强度;
  • 在彩色图像中,每个像素通常有三个值,分别表示红色、绿色和蓝色(RGB)通道的强度。

1.1 访问单个像素值

假设我们有一个灰度图像 image,可以通过 image[y, x] 来访问位于 (x, y) 位置的像素值。

// 读取图像
cv::Mat image = cv::imread("./gray.jpg", cv::IMREAD_COLOR);

// 读一个灰度图像像素点的像素值
int gray = image.at<uchar>(200, 100); // 访问 (200, 100) 位置的像素值

// 打印像素值
qDebug() << "pixValue:" << gray; // 打印结果:pixValue: 186

对于彩色图像,可以通过 image[y, x, c] 来访问各个特定通道的像素值。

// 读取图像
cv::Mat image = cv::imread("./test.jpg", cv::IMREAD_COLOR);

// 读一个彩色图像像素点的像素值
int b = image.at<Vec3b>(200, 100)[0]; // 获取row行col列0通道的像素值,Vec3b可以用来读取三通道的RGB图像像素值
int g = image.at<Vec3b>(200, 100)[1]; //获取row行col列1通道的像素值
int r = image.at<Vec3b>(200, 100)[2]; // 获取row行col列2通道的像素值

// 打印像素值
qDebug() << "pixValue:" << b << g << r; // 打印结果:pixValue: 203 228 232

1.2 遍历访问像素

代码如下:

// 读取图像
cv::Mat image = cv::imread("./gray.jpg", cv::IMREAD_COLOR);

// 遍历图像像素
int height = image.rows; // 获取图像行数
int width = image.cols; // 获取图像列数
for (int row = 0; row < height; row++) {//遍历图像各个像素点的像素值
  for (int col = 0; col < width; col++) {
    qDebug() << "[" << row << "," << col << "]:" << image.at<uchar>(row, col);
  }
}

打印结果如下:

[ 0 , 0 ]: 71
[ 0 , 1 ]: 71
[ 0 , 2 ]: 71
[ 0 , 3 ]: 72
[ 0 , 4 ]: 72
[ 0 , 5 ]: 72
[ 0 , 6 ]: 71
[ 0 , 7 ]: 71
[ 0 , 8 ]: 71
[ 0 , 9 ]: 74
[ 0 , 10 ]: 74
[ 0 , 11 ]: 74
[ 0 , 12 ]: 73

1.3 修改像素值

灰度图像:

// image.at<uchar>(row,col) = 目标像素值
image.at<uchar>(200,100) = 125; 

RGB 三通道图像:

//image.at<Vec3b>(row, col)[0] = 目标像素值; // 修改row行col列0通道的像素值
//image.at<Vec3b>(row, col)[1] = 目标像素值; // 修改row行col列1通道的像素值
//image.at<Vec3b>(row, col)[2] = 目标像素值; // 修改row行col列2通道的像素值

image.at<Vec3b>(200, 100)[0] = 0; // 修改row行col列0通道的像素值
image.at<Vec3b>(200, 100)[1] = 0; // 修改row行col列1通道的像素值
image.at<Vec3b>(200, 100)[2] = 255; // 修改row行col列2通道的像素值

1.4 去掉图像某一通道色彩

// 读一个彩色图像像素点的像素值
int b = image.at<Vec3b>(200, 100)[0]; // 获取row行col列0通道的像素值,Vec3b可以用来读取三通道的RGB图像像素值
int g = image.at<Vec3b>(200, 100)[1]; //获取row行col列1通道的像素值
int r = image.at<Vec3b>(200, 100)[2]; // 获取row行col列2通道的像素值

// 去掉图像某一通道色彩
image.at<Vec3b>(200, 100)[0] = b; // 保持row行col列0通道的像素值
image.at<Vec3b>(200, 100)[1] = g; // 保持row行col列1通道的像素值
image.at<Vec3b>(200, 100)[2] = 0; // 清零row行col列2通道的像素值

1.5 反转图像色彩

反转灰度图像:

// 访问 (200, 100) 位置的像素值
int gray = image.at<uchar>(200, 100); 
// 反转灰度图像
image.at<uchar>(200, 100) = 255 - gray;

反转 RGB 图像:

// 读一个彩色图像像素点的像素值
int b = image.at<Vec3b>(200, 100)[0]; // 获取row行col列0通道的像素值,Vec3b可以用来读取三通道的RGB图像像素值
int g = image.at<Vec3b>(200, 100)[1]; //获取row行col列1通道的像素值
int r = image.at<Vec3b>(200, 100)[2]; // 获取row行col列2通道的像素值

// 反转 RGB 图像
image.at<Vec3b>(200, 100)[0] = 255 - b; // 反转row行col列0通道的像素值
image.at<Vec3b>(200, 100)[1] = 255 - g; // 反转row行col列1通道的像素值
image.at<Vec3b>(200, 100)[2] = 255 - r; // 反转row行col列2通道的像素值

示例:

#include <QApplication>
#include <QDebug>

// 添加相关头文件和包
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 读取图像
    cv::Mat image = cv::imread("./test.jpg", cv::IMREAD_COLOR);

    // 遍历图像像素
    int height = image.rows; // 获取图像行数
    int width = image.cols; // 获取图像列数
    for (int row = 0; row < height; row++) {
      for (int col = 0; col < width; col++) {
          // 读一个彩色图像像素点的像素值
          int b = image.at<Vec3b>(row, col)[0]; // 获取row行col列0通道的像素值,Vec3b可以用来读取三通道的RGB图像像素值
          int g = image.at<Vec3b>(row, col)[1]; //获取row行col列1通道的像素值
          int r = image.at<Vec3b>(row, col)[2]; // 获取row行col列2通道的像素值

          // 反转 RGB 图像
          image.at<Vec3b>(row, col)[0] = 255 - b; // 反转row行col列0通道的像素值
          image.at<Vec3b>(row, col)[1] = 255 - g; // 反转row行col列1通道的像素值
          image.at<Vec3b>(row, col)[2] = 255 - r; // 反转row行col列2通道的像素值
      }
    }

    // 显示图像
    cv::imshow("Image", image);
    cv::waitKey(0);

    // 释放资源
    cv::destroyAllWindows();

    return a.exec();
}

原图如下:

Blog_OpenCV_Learnl_20.png


翻转后的效果图如下:

Blog_OpenCV_Learnl_21.png

二、获取图像属性

图像属性包括行数,列数,通道数,图像数据类型等等。

尺寸:图像的尺寸可以通过 rowscols 属性获取。

int height = image.rows;
int width = image.cols;
qDebug() << "height:" << height << "width:" << width; // 打印结果:height: 360 width: 640

通道数:图像的通道数可以通过 channels() 方法获取。

int channels = image.channels();
qDebug() << "channels:" << channels; // 打印结果:channels: 3

示例:

#include <QApplication>
#include <QDebug>

// 添加相关头文件和包
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 读取图像
    cv::Mat image = cv::imread("./test.jpg", cv::IMREAD_COLOR);

    // 获取图像属性
    int width = image.cols;  // 图像宽度
    int height = image.rows; // 图像高度
    int channels = image.channels(); // 图像通道数

    qDebug() << "图像宽度: " << width;
    qDebug() << "图像高度: " << height;
    qDebug() << "图像通道数: " << channels;

    return a.exec();
}

打印结果:

图像宽度:  640
图像高度:  360
图像通道数:  3

三、颜色空间转换

OpenCV 能够将同一幅图像从一个色彩空间转换到另一个色彩空间。可以将图像从 BGR色彩空间 转换到 GRAY色彩空间OpenCy 中有数百种关于在不同色彩空间之间转换的方法。当前,在计算机视觉中有三种常用的色彩空间:灰度、BGR 以及 HSV(Hue,Saturation,Value)。

  • 灰度色彩空间是通过去除彩色信息来将其转换成灰阶,灰度色彩空间对中间处理特别有效,比如人脸检测。
  • BGR,即蓝-绿-红色彩空间,每一个像素点都由一个三元数组来表示,分别代表蓝、绿、红三种颜色。网页开发者可能熟悉另一个与之相似的颜色空间:RGB,它们只是在颜色的顺序上不同。
  • HSV,H(Hue) 是色调,S(Saturation) 是饱和度,V(Value) 表示黑暗的程度(或光谱另一端的明亮程度)。

OpenCV 中用于转换图像色彩空间的函数是 cvtColor,其语法格式如下:

void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
  • src:转换前的初始图像
  • dst:转换后的图像
  • code:色彩空间转换码

转换码有以下几种:cv2.COLOR_GRAY2BGR(从 GRAY 色彩空间转换到 BGR 色彩空间)

  • COLOR_ BGR2GRAY(从 BGR 色彩空间转换到 GRAY 色彩空间)
  • COLOR_BGR2HSV(从 BGR 色彩空间转换到 HSV 色彩空间)
  • COLOR_HSV2BGR(从 HSV 色彩空间转换到 BGR 色彩空间)

示例

将 BGR 图像转换为灰度图像的示例:

cv::Mat src = cv::imread("./test.jpg", cv::IMREAD_COLOR);
cv::Mat gray;

// 将BGR图像转换为灰度图像
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);

四、数值类型转换

cv::convertTo 用于将矩阵的数值类型转换为另一种类型。这在图像处理中特别有用,比如当你需要将图像数据从一种位深度转换到另一种(例如从 8 位转换到 32 位浮点数),或者你需要调整数值范围时。

void Mat::convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
  • dst: 输出矩阵,它将存储转换后的结果。其大小和通道数与输入矩阵相同。
  • type: 指定目标矩阵的数据类型(如 CV_8U, CV_16U, CV_32F 等)。如果指定为 -1,则输出矩阵与输入矩阵具有相同类型。
  • alpha: 可选的比例因子,应用于源数组元素。默认值为 1。
  • beta: 可选的增量,添加到缩放值。默认值为 0。

示例:

// 加载灰度图像
cv::Mat src = cv::imread("./test.jpg", cv::IMREAD_GRAYSCALE);

// 目标图像
cv::Mat dst;

// 转换类型并调整数值范围
src.convertTo(dst, CV_32F, 1.0/255, 0); // 将像素值映射到 [0, 1] 区间

在这个例子中,我们首先加载了一张灰度图像。然后使用 convertTo 方法将图像从 CV_8U(默认的 8 位无符号整数格式)转换为 CV_32F(32 位浮点数),同时通过设置 alpha 参数为 1.0/255 来将像素值从 [0, 255] 映射到 [0, 1]


posted @ 2025-08-05 17:09  fengMisaka  阅读(228)  评论(0)    收藏  举报