OpenCV之访问图像中的像素

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

图像矩阵的大小取决于所用的颜色模型,确切的说,取决于所用通道数。如果是灰度图像,矩阵就如图所示:

对于多通道来说,矩阵中的列会包含多个子列,其子列个数与通道数相等,如图RGB颜色模型的矩阵:

可以看到,OpenCV中子列的通道顺序是反过来的-----BGR 而不是 RGB。

2、颜色空间缩减

如果矩阵元素存储的是单通道像素,使用C或者C++的无符号字符类型,像素可有256个不同值。

如果是三通道图像,这种存储格式的颜色数就太多了。256 * 256 * 256个不同颜色值

 3、计时函数

 4、访问图像中像素的三类方法

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/video.hpp>

using namespace cv;
using namespace std;

//方法一,用指针访问像素
void colorReduce1(Mat& inputImage, Mat& outputImage, int div);

//方法二,用迭代器操作像素
void colorReduce2(Mat& inputImage, Mat& outputImage, int div);

//方法三,动态地址计算
void colorReduce3(Mat& inputImage, Mat& outputImage, int div);

int main(int argc, char** argv)
{
	//1.创建原始图并显示
	Mat srcImage = imread("erha.jpg");
	imshow("name1", srcImage);

	//2.按原始图的参数规格来创建效果图
	Mat dstImage1, dstImage2, dstImage3;
	dstImage1.create(srcImage.rows, srcImage.cols, srcImage.type());//大小类型和原图片相同
	//3.记录起始时间
	double time0 = static_cast<double>(getTickCount());
	//4.调用颜色控件缩减函数
	colorReduce1(srcImage, dstImage1, 20);
	colorReduce2(srcImage, dstImage2, 40);
	colorReduce3(srcImage, dstImage3, 60);
	//5.计算运行时间并输出
	time0 = (double(getTickCount()) - time0) / getTickFrequency();

	cout << "此方法运行时间为: " << time0 << " 秒" << endl;
	//6.显示效果图
	imshow("效果图1", dstImage1);
	imshow("效果图2", dstImage2);
	imshow("效果图3", dstImage3);

	waitKey(0);
	return 0;
}

void colorReduce1(Mat& inputImage, Mat& outputImage, int div) {
	//参数准备
	outputImage = inputImage.clone(); //复制实参到临时变量
	int rowNumber = outputImage.rows;
	int colNumber = outputImage.cols * outputImage.channels();//列数 * 通道数 = 每一行元素的个数
	//双重循环,遍历所有像素值
	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;
		}
	}
}

void colorReduce2(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;
		(*it)[1] = (*it)[1] / div * div;
		(*it)[2] = (*it)[2] / div * div;
	}
}

void colorReduce3(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; //蓝色通道
			outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div * div; //绿色通道
			outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div * div; //红色通道
		}
	}
}

效果

 代码解析

猜你喜欢

转载自blog.csdn.net/sono_io/article/details/124308740