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();
}
原图如下:

翻转后的效果图如下:

二、获取图像属性
图像属性包括行数,列数,通道数,图像数据类型等等。
尺寸:图像的尺寸可以通过 rows 和 cols 属性获取。
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]。

浙公网安备 33010602011771号