【OpenCV + VS】OpenCV中的图像像素读写

        在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;
}

读取:通过
image.at<Vec3b>(i, j)
读取像素的BGR值,
Vec3b
是一个三通道的向量,表示BGR三个通道的值。你可以通过
pixel_value[0]
访问蓝色通道,
pixel_value[1]
访问绿色通道,
pixel_value[2]
访问红色通道。

修改:通过
image.at<Vec3b>(i, j) = Vec3b(B, G, R)
修改像素的BGR值。

四、通过指针直接访问像素

如果你需要更高效的访问(特别是处理大量图像像素时),可以使用指针直接访问
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
指针访问像素

对于更高效的读取和写入,尤其是在操作较大图像时,可以使用
Mat

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)
来读取和修改像素值。

多通道图像:使用
image.at<Vec3b>(i, j)
来读取和修改像素的BGR值。

使用指针访问
image.data
允许你通过指针直接访问图像的内存,适用于需要高效操作的场景。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容