【OpenCV(C++)】访问图像中的像素

图像在内存之中的存储方式

图像矩阵大小取决于所用的颜色模型,即所用的通道数。对于多通道图像来说,矩阵的列会包含多个子列,其子列个数与通道数相等。例如,RGB颜色模型的矩阵如图:
在这里插入图片描述
在OpenCV中子列的通道顺序是反过来的——BGR。

颜色空间缩减

颜色空间缩减可以大大降低运算复杂度,其做法是:将现有颜色空间值除以某个输入值,以获得较少的颜色数。

简单的颜色空间缩减算法可由两步组成:

  1. 遍历图像矩阵的每一个像素
  2. 对应像素应用公式
    在这里插入图片描述

访问图像中像素的三种方法

在OpenCV中,提供了三种访问每个像素的方法。

#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <iostream> 

using namespace std;
using namespace cv;

void colorReduce(Mat& inputImage, Mat& outputImage, int div);
void ShowHelpText();

int main()
{
	//【1】创建原始图并显示
	Mat srcImage = imread("pig.jpg");
	imshow("原始图像", srcImage);

	//【2】按原始图的参数规格来创建创建效果图
	Mat dstImage;
	dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//效果图的大小、类型与原图片相同 

	ShowHelpText();

	//【3】记录起始时间
	double time0 = static_cast<double>(getTickCount());

	//【4】调用颜色空间缩减函数
	colorReduce(srcImage, dstImage, 32);

	//【5】计算运行时间并输出
	time0 = ((double)getTickCount() - time0) / getTickFrequency();
	cout << "\t此方法运行时间为: " << time0 << "秒" << endl;  //输出运行时间

	//【6】显示效果图
	imshow("效果图", dstImage);
	waitKey(0);
}

1.用指针访问像素

void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
	//参数准备
	outputImage = inputImage.clone();  //拷贝实参到临时变量
	int rowNumber = outputImage.rows;  //行数
	int colNumber = outputImage.cols * outputImage.channels();  //列数 x 通道数=每一行元素的个数

	//双重循环,遍历所有的像素值
	for (int i = 0; i < rowNumber; i++)  //行循环
	{
		uchar* data = outputImage.ptr<uchar>(i);  //获取第i行的首地址
		for (int j = 0; j < colNumber; j++)   //列循环
		{
			// ---------【开始处理每个像素】-------------     
			data[j] = data[j] / div * div + div / 2;
			// ----------【处理结束】---------------------
		}  //行处理结束
	}
}

2.用迭代器访问像素

void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
	//参数准备
	outputImage = inputImage.clone();  //拷贝实参到临时变量
	//获取迭代器
	Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();  //初始位置的迭代器
	Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();  //终止位置的迭代器

	//存取彩色图像像素
	for (; it != itend; ++it)
	{
		// ------------------------【开始处理每个像素】--------------------
		(*it)[0] = (*it)[0] / div * div + div / 2;
		(*it)[1] = (*it)[1] / div * div + div / 2;
		(*it)[2] = (*it)[2] / div * div + div / 2;
		// ------------------------【处理结束】----------------------------
	}
}

3.用动态地址计算配合at访问像素

void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
	//参数准备
	outputImage = inputImage.clone();  //拷贝实参到临时变量
	int rowNumber = outputImage.rows;  //行数
	int colNumber = outputImage.cols;  //列数

	//存取彩色图像像素
	for (int i = 0; i < rowNumber; i++)
	{
		for (int j = 0; j < colNumber; j++)
		{
			// ------------------------【开始处理每个像素】--------------------
			outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div * div + div / 2;  //蓝色通道
			outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div * div + div / 2;  //绿色通道
			outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div * div + div / 2;  //红是通道
			// -------------------------【处理结束】----------------------------
		}  // 行处理结束     
	}
}
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是修补图像的反光部分的代码,供参考: ```c #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat img = imread("image.jpg"); Mat gray, mask; cvtColor(img, gray, COLOR_BGR2GRAY); threshold(gray, mask, 200, 255, THRESH_BINARY_INV); Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); morphologyEx(mask, mask, MORPH_CLOSE, kernel); inpaint(img, mask, img, 3, INPAINT_TELEA); imshow("Result", img); waitKey(); return ; } ``` 以上代码使用了 OpenCV 库,首先读取图像,将其转换为灰度图像,然后使用阈值处理得到反光部分的掩膜,接着使用形态学闭运算去除掩膜的小孔,最后使用修补算法 inpaint 进行修补。 ### 回答2: 要修补图像的反光部分,可以使用OpenCV图像处理函数来实现。首先,需要进行图像预处理,将图像转换成灰度图像,以便更好地处理。然后,可以使用阈值函数对图像进行二值化处理,将反光部分与其他部分区分开来。 在处理反光部分前,需要找到图像的高亮区域。可以使用OpenCV的亮度调整函数来增强图像的亮度。然后,使用阈值函数将高亮区域二值化,得到反光部分的掩码。通过计算图像的亮度差异,可以根据掩码将反光部分与其他部分区分开来。 接下来,可以使用修复函数来修补反光部分。可以使用OpenCV图像修复函数来实现,通过对反光部分进行填充、修复或者利用周围像素进行纹理合成等方法来修复图像。 对于反光部分较小的情况,可以使用OpenCV的插值函数进行插值处理,将反光部分与其他部分进行平滑过渡。 最后,根据需求可以进行后处理,如调整图像的对比度、亮度等来进一步改善修补效果。 总之,代码的基本思路是对图像进行预处理,找到反光部分的位置,进行修复处理,并根据需求进行后处理,以改善修补效果。 ### 回答3: 以下是使用OpenCV C++修补图像的反光部分的代码: ```cpp #include <opencv2/opencv.hpp> using namespace cv; void removeReflection(Mat &image) { Mat grayscale; cvtColor(image, grayscale, COLOR_BGR2GRAY); Mat blurred; medianBlur(grayscale, blurred, 15); Mat edges; Laplacian(blurred, edges, CV_8U); Mat mask; threshold(edges, mask, 25, 255, THRESH_BINARY_INV); Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); morphologyEx(mask, mask, MORPH_CLOSE, kernel); Mat repaired; inpaint(image, mask, repaired, 3, INPAINT_TELEA); image = repaired; } int main() { Mat image = imread("input.jpg"); if (image.empty()) { std::cout << "Could not open or find image." << std::endl; return -1; } removeReflection(image); imshow("Repaired Image", image); waitKey(0); return 0; } ``` 这段代码通过以下步骤修补图像的反光部分: 1. 将彩色图像转换为灰度图像。 2. 对灰度图像进行值滤波以平滑图像。 3. 使用Laplacian算子检测图像的边缘。 4. 根据边缘图像生成反光区域的掩码。 5. 使用膨胀操作关闭掩码的小孔和毛刺。 6. 利用修复算法将反光区域修补为周围颜色的估计值。 7. 显示修补后的图像

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值