opencv中Mat格式,图像读入与像素获取

常用的基本函数
在这里插入图片描述
在这里插入图片描述

Mat矩阵的定义

data:Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存 (uchar* data)

dims:Mat所代表的矩阵的维度,如 3 * 4 的矩阵为 2 维, 3 * 4 * 5 的为3维

channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说 3 * 4 矩阵中一共 12 个元素,如果每个元素有三个值,那么就说这个矩阵是 3 通道的,即 channels = 3。常见的是一张彩色图片有红、绿、蓝三个通道。

depth:深度,即每一个像素的位数(bits),在opencv的Mat.depth()中得到的是一个 0 – 6 的数字,分别代表不同的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 可见 0和1都代表8位, 2和3都代表16位,4和5代表32位,6代表64位;

step:是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意 step1 (step / elemSize1),M.step[m-1] 总是等于 elemSize,M.step1(m-1)总是等于 channels;

elemSize : 矩阵中每一个元素的数据大小,如果Mat中的数据的数据类型是 CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,CV_16UC2 那么 elemSize = 4;记住另外有个 elemSize1 表示的是矩阵中数据类型的大小,即 elemSize / channels 的大小

获取某一点的像素点

最快的获取形式

Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
{
	// accept only char type matrices
	CV_Assert(I.depth() != sizeof(uchar));
	int channels = I.channels();
	int nRows = I.rows ;
	int nCols = I.cols* channels;
	if (I.isContinuous())
	{
		nCols *= nRows;
		nRows = 1;
	}
	int i,j;
	uchar* p;
	for( i = 0; i < nRows; ++i)
	{
		p = I.ptr<uchar>(i);
		for ( j = 0; j < nCols; ++j)
		{
			p[j] = table[p[j]];
		}
	}
	return I;
}

获其中一个点的函数

//获得某点像素值
int get_pixel(Mat & img, Point pt) {
	int width = img.cols; //图片宽度
	int height = img.rows; //图片宽度t;//图片高度
	// x 是 列 , y 是 行
	uchar* ptr = (uchar*) img.data + pt.y * width; //获得灰度值数据指针
	int intensity = ptr[pt.x];
	return intensity;
}

Mat最直接的访问方法是通过.ptr<>函数得到一行的指针,并用[]操作符访问某一列的像素值。
注意不可以像matlab中直接‘img[1][1]’来获取第一个元素,因为openCV应该没有重构这个[i][j]操作符。


// using .ptr and []
void colorReduce0(cv::Mat &image, int div=64) {
	  int nr= image.rows; // number of rows
	  int nc= image.cols * image.channels(); // total number of elements per line
      for (int j=0; j<nr; j++) {
		  uchar* data= image.ptr<uchar>(j);
          for (int i=0; i<nc; i++) {
                  data[i]= data[i]/div*div + div/2;
            }                  
      }

灰度图存储可视化:
在这里插入图片描述
三通道彩色图存储可视化:
在这里插入图片描述

这是使用opencv中自己定义的at函数来取像素值,代码如下,函数更为简洁,但是速度方面却更慢。这个例子也可以看出opencv的图像存储格式是HWC,其中最后的channel是按照BGR的格式来存放的,通过【0】来获取Blue通道的值。

// using (j,i)
void colorReduce11(cv::Mat &image, int div=64) {
	  int nr= image.rows; // number of rows
	  int nc= image.cols; // number of columns
      for (int j=0; j<nr; j++) {
          for (int i=0; i<nc; i++) {
                  image.at<cv::Vec3b>(j,i)[0]=	 image.at<cv::Vec3b>(j,i)[0]/div*div + div/2;
                  image.at<cv::Vec3b>(j,i)[1]=	 image.at<cv::Vec3b>(j,i)[1]/div*div + div/2;
                  image.at<cv::Vec3b>(j,i)[2]=	 image.at<cv::Vec3b>(j,i)[2]/div*div + div/2;
            } // end of row                 
      }
}

在这里插入图片描述
在这里插入图片描述

不同获取方式的速度对比:https://blog.csdn.net/xiaowei_cqu/article/details/19839019

关于step和elemSize的讲解:https://blog.csdn.net/dcrmg/article/details/52294259?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值