《OpenCV3学习笔记》1.2 Mat详解 :Mat数据逐像素读写

     Mat矩阵中每一个元素代表一个像素,灰度图像,像素用8U 无符号数,0黑色,255白色;彩色图像,每个像素需要3位这样的8U表示,即三个通道(R、G、B),矩阵依次存储一个像素的三个通道值,然后再存储下一个像素点。

      灰度图像素类型uchar;    彩色图像素点类型Vec3b

计时

double time0 = static_cast<double>(getTickCount());
{

}
time0 = ((double)getTickCount()-time0)/getTickFrequency();

压缩颜色空间

在一幅数字图像存储的矩阵一般是uchar类型,为8位256个值。如果是三通道图形,那么应该有256*256*256=16581375种不同的颜色,这1600多万种颜色,数据量会很大,影响后期的处理,这个时候,我们就需要将颜色空间进行缩减。

       对于三通道图像,本来有256*256*256种颜色,这里我们取:

       0-9的像素取值:0

       10-19的像素取值:1

       ……

       250-256的像素取值:25

本节对应数学表达公式:I(x,y)= I(x,y)/div *div + div/2;

  主程序

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

//颜色空间缩减函数
void colorreduce(Mat& input, Mat& output, int div);

int main()
{
	//原图像
	Mat src = imread("dota.png");
	imshow("原图像", src);
	//生成图像
	Mat dest;
	dest.create(src.rows, src.cols, src.type());
	//颜色缩减
	double time0 = static_cast<double>(getTickCount());
	colorreduce(src, dest, 64);
	time0 = ((double)getTickCount() - time0) / getTickFrequency();
	cout << "运行时间" << time0 << "秒" << endl;
	imshow("生成图像", dest);

	waitKey();
	return 0;
}

1、迭代器

void colorreduce(Mat& input, Mat& output, int div)
{

	output = input.clone();
        //迭代器
	MatIterator_<Vec3b> it, end;
  //或者Mat_<Vec3b>::iterator it, end;
	it = output.begin<Vec3b>();
	end = output.end<Vec3b>();

	for (; it < end; 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;
	}
}

2、指针

提供ptr函数访问任意一行像素的首地址,特别方便图像的一行一行的横向访问。

速度很快。

//获取像素指针
uchar * p = output.ptr<uchar>(i);
Vec3b * p = output.ptr<Vec3b>(i);

void colorreduce(Mat& input, Mat& output, int div)
{

	output = input.clone();
	int row = input.rows;
	int cols = input.cols*input.channels();//每一行元素个数

	for (int i = 0; i < row; i++)
	{
		//需要在output上进行更改
		uchar* data = output.ptr<uchar>(i);
		for (int j = 0; j < cols; j++)
		{
			data[j] = data[j] / div*div + div / 2;
		}
	}
}



 或者

//彩色图
	for (int i = 0; i < colorim.rows; ++i)
	{

		//获取第 i 行首像素指针
		Vec3b * p = colorim.ptr<Vec3b>(i);
		for (int j = 0; j < colorim.cols; ++j)
		{
			//三通道
			p[j][0] = i % 255; //Blue
			p[j][1] = j % 255; //Green
			p[j][2] = 0; //Red
		}
	}

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; //红色通道
        }
    }

}

猜你喜欢

转载自blog.csdn.net/try_again_later/article/details/81475673