opencv入门(5)图像像素的读写操作和算术运算

发布于:2025-07-03 ⋅ 阅读:(24) ⋅ 点赞:(0)


1 图像遍历与修改

C++中支持 数组遍历 和 指针方式遍历

1.1 使用数组

访问使用 image.at(row,col) 进行访问
如果是单通道灰度图,就使用image.at进行读取
如果是三通道彩色图,就使用Image.at进行读取单个像素,通过 Image.at [0], Image.at[1], Image.at[2]读取每个通道的数据

void QuickDemo::pixel_visit_demo(Mat &image)
{
	int w = image.cols;
	int h = image.rows;
	int dimis = image.channels();
	for (int row = 0; row < h; row++)
	{
		for (int col = 0; col < w; col++)
		{
			if (dimis == 1)
			{
				// 灰色图像 打印像素 几行几列的那个像素点
				int pv = image.at<uchar>(row, col);
				// 修改像素点
				image.at<uchar>(row, col) = 255 - pv;

			}
			if (dimis == 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);

}

这边就是对三通道进行一个取反
在这里插入图片描述
在这里插入图片描述

1.2 使用指针

使用image.ptr 进行遍历

for (int row = 0; row < h; row++)
	{
		uchar* current_row = image.ptr<uchar>(row);
		
		for (int col = 0; col < w; col++)
		{
			if (dimis == 1)
			{
				// 灰色图像 打印像素 几行几列的那个像素点
				int pv = *current_row;
				// 修改像素点
				*current_row++ = 255 - pv;

			}
			if (dimis == 3)
			{
				// 彩色图像 专门获取三通道的存储
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;

			}
		}
	}

2 图像的算术运算

2.1 一般算术操作

Mat dst;
	dst = image + Scalar(50, 50, 50);
	imshow("加法测试");

在这里插入图片描述
同样可以使用减法,除法

Mat dst;
	dst = image - Scalar(50, 50, 50);
	dst = image / Scalar(2, 2, 2);
	
	imshow("加法测试");

进行乘法时会报错,这时候需要特殊操作
使用multiply 进行乘法操作

	Mat dst;
	//dst = image + Scalar(50, 50, 50);
	
	Mat m = Mat::zeros(image.size(), image.type());
	multiply(image, m, dst);
	imshow("加法测试");

会进行截断操作,超过255会变成255

为避免加法也会出现超过255的操作,使用C++的数据类型转换,
saturate_cast(a,b);

Mat dst = Mat::zeros(image.size(), image.type());
		//dst = image + Scalar(50, 50, 50);
	
		Mat m = Mat::zeros(image.size(), image.type());

		/*multiply(image, m, dst);
		imshow("加法测试");*/

		m = Scalar(50, 50, 50);

		int w = image.cols;
		int h = image.rows;
		int dimis = image.channels();
		for (int row = 0; row < h; row++)
		{
			for (int col = 0; col < w; col++)
			{
				if (dimis == 1)
				{
					// 灰色图像 打印像素 几行几列的那个像素点
					int pv = image.at<uchar>(row, col);
					// 修改像素点
					image.at<uchar>(row, col) = 255 - pv;

				}
				if (dimis == 3)
				{
					// 彩色图像 专门获取三通道的存储
					Vec3b p1 = image.at<Vec3b>(row, col);
 					Vec3b p2 = m.at<Vec3b>(row, col);
					image.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);
					image.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);
					image.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);

				}
			}
		}

2.2 算术API

上节已经有乘法的API
multiply(第一个mat,第二个mat, 输出结果);
加法
add(image, m, dst);
减法
subtract(image , m, dst)
除法
divide(image, m, dst)

multiply(image, m, dst);
add(image, m, dst);
subtract(image, m, dst);
divide(image, m, dst);

网站公告

今日签到

点亮在社区的每一天
去签到