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

xiaoxiao2021-03-01  69

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

 

 

转载请注明原文地址: https://www.6miu.com/read-4199986.html

最新回复(0)