在OpenCV中,图像是以(矩阵)类型存储的。每个像素可以通过访问图像矩阵中的元素来进行读取和修改。理解如何读取和修改图像的像素是图像处理的基础。
Mat
一、图像像素的存储结构
单通道图像:每个像素用一个数值表示,通常是灰度值(例如0-255的值)。
多通道图像:例如BGR图像,每个像素由三个数值表示,分别代表蓝色、绿色和红色的强度。
OpenCV提供了多种方法来访问图像的像素值,我们将介绍几种常用的方法。
二、访问单通道图像像素
对于单通道图像(如灰度图像),每个像素的值直接表示亮度信息。访问像素时,对象的每个元素可以通过
Mat来访问,其中
at<T>(i, j)是图像的数据类型(例如
T)。
uchar
示例:读取和修改灰度图像的像素
// 访问单通道图像像素
//读取和修改灰度图像的像素
void rwGrayPic(Mat image = cv::imread("gray.jpg"))
{
// 获取图像的大小
int rows = image.rows;
int cols = image.cols;
std::cout << "图像尺寸:" << rows << "行(高)," << cols << "列(宽)" << std::endl;
std::cout << "通道数:" << image.channels() << std::endl;
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
std::cout << "转换后通道数:" << gray.channels() << std::endl; // 若仍为3,则异常
// 读取某个像素的值
uchar pixel_value = gray.at<uchar>(100, 100); // 读取(100, 100)位置的像素值
std::cout << "Pixel value at (100, 100): " << (int)pixel_value << std::endl;
// 修改某个像素的值
gray.at<uchar>(100, 100) = 255; // 设置(100, 100)位置的像素值为255(白色)
//修改一堆像素的值
for(int i=0;i<1000;i++)
for(int j=0;j<1000;j++)
gray.at<uchar>(i, j) = 255;
// 设定缩放比例(例如缩小到原来的50%)
double scale = 0.1;
Mat resized;
resize(gray, resized, Size(), scale, scale); // 按比例缩放
// 显示修改后的图像
imshow("Modified Image", resized);
waitKey(0);
}
int main()
{
rwGrayPic();
return 0;
}
读取:通过获取位置
image.at<uchar>(i, j)的像素值。
(i, j)
修改:通过来修改某个像素的值。
image.at<uchar>(i, j) = value
Pixel value at (100, 100): 34

三、访问多通道图像像素
对于多通道图像(如BGR图像),每个像素包含多个通道,每个通道用一个值表示颜色分量。例如,BGR图像的每个像素有三个分量:蓝色、绿色和红色。
示例:读取和修改BGR图像的像素
void rwRGBPic(Mat image = cv::imread("恐非太.jpg"))
{
//if (image.empty()) {
// std::cout << "Image not loaded!" << std::endl;
// return -1;
//}
// 获取图像的大小
int rows = image.rows;
int cols = image.cols;
// 读取某个像素的BGR值
Vec3b pixel_value = image.at<Vec3b>(100, 100); // 读取(100, 100)位置的像素值
std::cout << "BGR Pixel value at (100, 100): "
<< "B: " << (int)pixel_value[0] << " "
<< "G: " << (int)pixel_value[1] << " "
<< "R: " << (int)pixel_value[2] << std::endl;
// 修改某个像素的BGR值
image.at<Vec3b>(100, 100) = Vec3b(0, 255, 0); // 设置(100, 100)位置的像素为绿色
//修改一堆像素的值
for (int i = 0; i < 1000; i++)
for (int j = 0; j < 1000; j++)
image.at<Vec3b>(i, j) = Vec3b(0, 255, 0);
// 设定缩放比例(例如缩小到原来的50%)
double scale = 0.1;
Mat resized;
resize(image, resized, Size(), scale, scale); // 按比例缩放
// 显示修改后的图像
imshow("Modified Image", resized);
waitKey(0);
}
int main()
{
rwRGBPic();
return 0;
}
读取:通过读取像素的BGR值,
image.at<Vec3b>(i, j)是一个三通道的向量,表示BGR三个通道的值。你可以通过
Vec3b访问蓝色通道,
pixel_value[0]访问绿色通道,
pixel_value[1]访问红色通道。
pixel_value[2]
修改:通过修改像素的BGR值。
image.at<Vec3b>(i, j) = Vec3b(B, G, R)

四、通过指针直接访问像素
如果你需要更高效的访问(特别是处理大量图像像素时),可以使用指针直接访问数据。指针访问更适合在处理大图像时减少时间消耗。
Mat
示例:使用指针遍历和修改图像像素
#include<opencv2/opencv.hpp>
#include <string.h>
using namespace cv;
const std::string picpath = "C:UsersZZMPictures豆绘AI_3711794.jpg";
int main() {
// 读取彩色图像
Mat image = imread(picpath);
if (image.empty()) {
std::cout << "Image not loaded!" << std::endl;
return -1;
}
// 获取图像的行数和列数
int rows = image.rows;
int cols = image.cols;
// 访问每个像素并修改
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 使用指针访问像素值
Vec3b& pixel = image.at<Vec3b>(i, j); // 获取(i, j)位置的像素的引用
pixel[0] = 0; // 修改蓝色通道值
pixel[1] = 0; // 修改绿色通道值
pixel[2] = 255; // 修改红色通道值
}
}
// 缩放比例(0.1 表示缩小到 10%)
double scale = 0.1;
int targetWidth = image.cols * scale; // 新宽度 = 原宽度 × 比例
int targetHeight = image.rows * scale; // 新高度 = 原高度 × 比例
Mat resizedImage;
resize(image, resizedImage, Size(targetWidth, targetHeight));
// 显示修改后的图像
imshow("Modified Image", resizedImage);
waitKey(0);
return 0;
}
通过获取像素值的引用,这样就可以直接修改像素的各个通道的值。此方法比通过
Vec3b &pixel = image.at<Vec3b>(i, j)每次访问都拷贝数据更高效。
at()
五、通过
data指针访问像素
data
对于更高效的读取和写入,尤其是在操作较大图像时,可以使用的
Mat指针直接访问图像数据。
data
示例:使用
data指针遍历和修改图像像素
data
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
// 读取彩色图像
Mat image = imread("image.jpg");
if (image.empty()) {
std::cout << "Image not loaded!" << std::endl;
return -1;
}
// 获取图像的总字节数
int channels = image.channels(); // 获取图像的通道数
int rows = image.rows;
int cols = image.cols;
uchar* data = image.data; // 获取图像的指针
// 通过指针访问和修改像素
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int index = (i * cols + j) * channels; // 计算像素的位置
data[index] = 0; // 修改蓝色通道
data[index + 1] = 0; // 修改绿色通道
data[index + 2] = 255; // 修改红色通道
}
}
// 显示修改后的图像
imshow("Modified Image", image);
waitKey(0);
return 0;
}
使用指针:
data对象的
Mat指针指向图像数据的第一个字节,可以通过直接操作这个指针来访问图像的所有像素。对于每个像素,可以通过计算索引来直接修改图像。
data
六、总结
单通道图像:使用来读取和修改像素值。
image.at<uchar>(i, j)
多通道图像:使用来读取和修改像素的BGR值。
image.at<Vec3b>(i, j)
使用指针访问:允许你通过指针直接访问图像的内存,适用于需要高效操作的场景。
image.data



![在苹果iPhone手机上编写ios越狱插件deb[超简单] - 鹿快](https://img.lukuai.com/blogimg/20251123/23f740f048644a198a64e73eeaa43e60.jpg)













暂无评论内容