Mat和图片

opencv2及之后采用面向对象编程,Mat类存储图片数据。

python&opencv中一幅彩色图片的数据结构可以看作3维的,它是庞大的 二维元组,其中每个元素又为像素元组,像素元组中元素为3个数字。我们知道一个像素代表一个点,这个点的颜色是由三原色混合而成,那个 元组的3个数字就代表3原色的数值以不同的数量混合就成了,各种颜色。
opencv&c++中图片数据用Mat存储,Mat数据主要是信息头和图片数据矩阵组成。

信息头内容包括:
1–矩阵的尺寸----比如—class Mat这个类中的----数据成员rows,cols—指定图像的尺寸
2–存储方法------对应—各种Mat的构造函数
3–存储地址
4–和一个指向----存储所有像素值的矩阵的----指针
一个Mat对象占内存最大的就是图片数据矩阵了,一幅300400图片就有300400=120000个像素,每个像素3个原色(3通道)的数值我们用uchar类型存储,3600008bit=360000Byte=360KB。当然并不是所有图片都是彩色图片,灰度图片就是只有一个颜色通道的黑白图片,灰度图片是以后经常使用的图片。
c++开发opencv力求实时运算,算法速度上要尽量快。所以opencv&c++用2维数组表示方便访问快速遍历,每三个元素代表一个像素,矩阵大小为rows
(cols*3),一定要注意rows和cols是图像像素的行列数目,而非c++中mat的图片数据矩阵的行列数。

可以cout打印该二维数组,一定要选用小图片,否则打印时间太长。

#include<opencv2\opencv.hpp>
#include<iostream>


using namespace cv;//一定要有
using namespace std;

int main(){
	Mat src = imread("D:/s.jpg");
	cout << src << endl;
	waitKey(0);
}

由于图片没有特别小的,没法数清他的行列。那我们呢自己定义Mat更容易看清他的结构。

#include<opencv2\opencv.hpp>
#include<iostream>

#include<Windows.h>
using namespace cv;//一定要有
using namespace std;

int main(){
	Mat mat(4, 3, CV_8UC3, Scalar(0, 230, 45));//4*3大小的图片,像素为3通道uchar类型,每个像素都为(0,230,45)
	cout << mat << endl;
	Sleep(30000);//没有图像显示时waitkey无效,我们调用休眠来暂停
}

结果:
在这里插入图片描述Mat的构造函数有很多:

	Mat mat1;
	mat1.create(200, 200, CV_8UC3);//像其他基本数据类型,如果未指定像素,像素为3原色默认数字的像素
	
	Mat mat2=Mat::ones(200, 200, CV_8UC3);//全为(1,1,1)
	
	Mat mat3=Mat::zeros(200, 200, CV_8UC3);//全为(0,0,0)
	
	Mat mat4(200,200,CV_8UC3);
	
	Mat mat5 = (Mat_<double>(3,3)<<3,3,3,2,2,2,1,1,1);//Mat_本身是一个模板类,其中的一个模板专用于图片存储重命名为Mat

那模我们怎末才能访问Mat中的像素呢?大概有三种推荐第一种。

我们如果打算将每个像素的每个通道值(每个原色)改为:new = old / (n*n) + n / 2;可以这样做:
定义函数参数src为待访问的图片Mat,dst为盛放像素值映射后图片的Mat,n是关于映射的系数。
【1】

void ColorReduce(Mat& src, Mat& dst, int n){
	dst = src.clone();
	int rownum = src.rows;
	int colnum = src.cols*src.channels();
	int i, j;
	for (i = 0; i < rownum; i++){
		uchar* fred = dst.ptr<uchar>(i);

		for (j = 0; j < colnum; j++)
			fred[j] = fred[j] / (n*n) + n / 2;
	}


}
【2】
void ColorReduce1(Mat& src, Mat& dst, int n){
	dst = src.clone();
	Mat_<Vec3b>::iterator it = dst.begin<Vec3b>();
	Mat_<Vec3b>::iterator itend = dst.end<Vec3b>();
	for (; it!=itend; it++){
		(*it)[0] = (*it)[0] / (n*n) + n / 2;
		(*it)[1] = (*it)[1] / (n*n) + n / 2;
		(*it)[2] = (*it)[2] / (n*n) + n / 2;
	}
}
【3】
void ColorReduce2(Mat& src, Mat& dst, int n){
	dst = src.clone();
	int i, j;
	for (i = 0; i < dst.rows; i++)
		for (j = 0; j < dst.cols; j++){
			dst.at<Vec3b>(i, j)[0] = ((dst.at<Vec3b>(i, j)[0]) / (n*n))+n/ 2;
			dst.at<Vec3b>(i, j)[1] = ((dst.at<Vec3b>(i, j)[1]) / (n*n)) + n / 2;
			dst.at<Vec3b>(i, j)[2] = ((dst.at<Vec3b>(i, j)[2]) / (n*n)) + n / 2;
		}
}

我随便用了一张图片,其中第一种运行时间约为0.006秒后面两种比第一种多近40倍的时间。我们详细介绍第一种,后面两种了解:
关键是ptr(i),这是一个Mat成员函数,是一个返回安全指针的模板函数,使用时必须指明Mat数组中元素类型,返回第i行的首地址。
获得某一行的首地址就可以访问此行数据,要注意前面说的Mat结构:一行有src.chanels()*src.cols列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值