image.at
在OpenCV中,使用Mat对象表示图像数据,在使用at方法时,需要确保使用正确的数据类型(如uchar或Vec3b),这取决于图像的通道数和数据深度。
单通道图像
对于单通道图像(如灰度图像),每个像素值由一个字节表示,范围是0到255。可以使用uchar类型来访问和修改像素值:
// 访问位于(y, x)的像素值
uchar pixelValue = image.at<uchar>(y, x);
// 修改位于(y, x)的像素值
image.at<uchar>(y, x) = newValue;
 
多通道图像
对于多通道图像(如RGB彩色图像),每个像素由多个值组成(在RGB图像中是3个值,分别对应红、绿、蓝通道)。要访问这种图像的像素,可以使用Vec3b类型,这是一个包含3个uchar值的向量,对应于一个像素的所有通道:
// 访问位于(y, x)的像素的所有通道
Vec3b pixelValue = image.at<Vec3b>(y, x);
// 访问特定通道(例如蓝色通道)
uchar blueValue = pixelValue[0];
// 修改位于(y, x)的像素的红色通道值
image.at<Vec3b>(y, x)[2] = newValue; // 对于RGB图像,索引2通常对应红色通道
 
应用示例1-没有用到指针
quick_opencv.h
#include<opencv2\opencv.hpp>
using namespace cv;
class QuickDemo{
    public:
		void pixel_visit_demo_nopointer(Mat &image);//图像像素读写
};
 
QuickDemo.cpp
#include<quick_opencv.h>
//图像像素读写
void QuickDemo::pixel_visit_demo_nopointer(Mat &image) {
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();
	for (int row = 0; row < h; row++) {
		for (int col = 0; col < w; col++) {
			if (dims == 1) {
				int pv = image.at<uchar>(row, col);
				image.at<uchar>(row, col) = 255 - pv;
			}
			if (dims == 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);
}
 
主函数main.cpp
#include<opencv2/opencv.hpp>
#include<quick_opencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
	
	//读取并显示图像,如果imread返回的Mat对象(src)是空的,打印错误消息并退出程序。
	Mat src = imread("C:/Users/Desktop/opencv-0/win.png");//B G R 蓝绿红
	if (src.empty())
	{
		printf("could not find the image...\n");
		return -1;
	}
	namedWindow("输入窗口", WINDOW_FREERATIO);//创建一个可以自由调整比例的窗口
	imshow("输入窗口", src);
	//创建QuickDemo类的实例qd
	QuickDemo qd;
	//像素读写
	qd.pixel_visit_demo_nopointer(src);
	
	//等待用户输入并清理资源
	waitKey(0);
	destroyAllWindows();
	return 0;
}
 


 可以利用image.ptr结合指针对上述代码进行优化,优化结果会简洁代码并且提高运行速度。
image.ptr
在OpenCV中,cv::Mat类的ptr方法用于获取指向图像数据某一行的指针。通过这个指针,可以直接访问和修改图像数据。这种方法比使用at方法访问单个像素值更快,特别是在需要遍历图像所有像素或进行大量像素级操作时。但是,使用指针访问数据需要更加小心,以避免越界访问和其他内存错误。
uchar* ptr = image.ptr<uchar>(y);
 
y是图像中行的索引(行号)。
 <uchar>指定了数据的类型。对于单通道的灰度图像,可以使用uchar(无符号字符)。对于多通道图像,可能需要使用不同的类型,例如Vec3b对于一个3通道的BGR图像。
获取了指针后,可以通过指针运算来访问或修改像素值。例如,修改第y行第x列像素的值:
ptr[x] = newValue; // 对于灰度图像
 
Vec3b* ptr = image.ptr<Vec3b>(y);// 对于多通道图像
ptr[x] = Vec3b(blue, green, red); // 设置像素值
 
或者直接访问和修改特定通道的值:
ptr[x][0] = newBlue;  // 修改蓝色通道的值
ptr[x][1] = newGreen; // 修改绿色通道的值
ptr[x][2] = newRed;   // 修改红色通道的值
 
应用示例2-用到指针
quick_opencv.h
#include<opencv2\opencv.hpp>
using namespace cv;
class QuickDemo{
    public:
		void pixel_visit_demo_usepointer(Mat &image);//图像像素读写
};
 
QuickDemo.cpp
#include<quick_opencv.h>
//图像像素读写
void QuickDemo::pixel_visit_demo_usepointer(Mat &image) {
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();
	for (int row = 0; row < h; row++) {
		uchar* current_row= image.ptr<uchar>(row);
		for (int col = 0; col < w; col++) {
			if (dims == 1) {
				int pv = *current_row;
				*current_row++ = 255 - *current_row;
			}
			if (dims == 3) {
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
			}
		}
	}
	imshow("像素读写演示结果", image);
}
 
主函数main.cpp
#include<opencv2/opencv.hpp>
#include<quick_opencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
	
	//读取并显示图像,如果imread返回的Mat对象(src)是空的,打印错误消息并退出程序。
	Mat src = imread("C:/Users/Desktop/opencv-0/win.png");//B G R 蓝绿红
	if (src.empty())
	{
		printf("could not find the image...\n");
		return -1;
	}
	namedWindow("输入窗口", WINDOW_FREERATIO);//创建一个可以自由调整比例的窗口
	imshow("输入窗口", src);
	//创建QuickDemo类的实例qd
	QuickDemo qd;
	//像素读写
	qd.pixel_visit_demo_usepointer(src);
	
	//等待用户输入并清理资源
	waitKey(0);
	destroyAllWindows();
	return 0;
}
 

 










![[嵌入式系统-28]:开源的虚拟机监视器和仿真器:QEMU(Quick EMUlator)与VirtualBox、VMware Workstation的比较](https://img-blog.csdnimg.cn/direct/74dd6cd2550d4afca4b054b1c0b9c22f.png)








