【OpenCV】一、单像素操作(将RGB图转为灰度图)

本文主要介绍了OpenCV中Mat矩阵的基础概念。包括data指针指向矩阵首地址,elemSize表示矩阵元素的数据大小,与数据类型和通道数有关,step指出图像各梯级在内存中占据的字节数,还给出了元素地址的计算公式及二维数组情况的简化公式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基础概念

1、data:unchar类型的指针,指向Mat矩阵的首地址,可以理解为表示一个房屋的门牌号。

2、elemSize:

elem是element(元素)的缩写,表示矩阵中每一个元素的数据大小,如果Mat中的数据类型是CV_8UC1,那么             elemSize==1;如果是CV_8UC3或CV_8SC3,那么elemSize==3;如果是CV_16UC3或者CV_16SC3,那么             elemSize==6;即elemSize是以8位(一个字节)为一个单位,乘以通道数和8位的整数倍

可以理解为整个房间可以睡多少人,这个时候就得累计上房间内所有床位数(通道)和每张床的容纳量了;

3、step:

step这里指出的是图像在各个梯级上的字节数大小,而这里的梯级指的是构成图像的名层次。
       上图三维图像由一个一个名面(第一级)构成,每一个平面由一行一行(第二级)构成,每行由一个一个点(第三级)构成。
        同理:二维图像由一行一行(第一级)构成,而每一行又由一个一个点(第二级)构成。
       Mat中的step[0]就是我们每一个第一级,在内存中占据的字节数量。例如,二维图像中step[0]就是每一行(第一级)在矩阵内存中,占据的字节的数量。也就是说step[i]就是第i+1级在矩阵内存中占据的字节的数量。
      
      M 数组的数据布局是由阵列  M.step[]定义的,使元素的地址(i0,。。。。iM.dims-1),其中 0<= ik < M.size [k],可以计算为:
addr( Mi0 ;:::;iM.dims-1) = M.data+ M.step[ 0]*i0 + M.step[ 1] *i1 + .…+ M.step[ M:dims- 1] iM:dims- 1
2维的数组的情况下根据上述公式被减至:
addr( Mi,j)= M.data+ M.step[ 0]*i+ M.step[ 1] *j
 

// 此代码展示将彩色图转换为灰度图
#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("C:/Users/lenovo/Pictures/Saved Pictures/Lena.png");
	Mat dst;
	cv::Size size = src.size();
	typedef double pixel_t;	// 定义像素类型
	if (dst.empty())
		dst.create(size, CV_64F);
	uchar* srcData = src.data;
	pixel_t* dstData = (pixel_t*) dst.data;
	int dstStep = dst.step / sizeof(dstData[0]);    // sizeof(dstData[0])=8,因为像素数据类型为double, 64位,8字节.
	int srcStep = src.step / sizeof(srcData[0]);    // step表示每行的字节数

	int numRow = src.rows;
	int numCol = src.cols;
	int numChannel = src.channels();
	cout << "numRow:" << numRow << endl;
	cout << "numCol:" << numCol << endl;
	cout << "src.channels:" << numChannel << endl;
	cout << "src.step:" << src.step << endl;
	cout << "sizeof(dstData[0]):" << sizeof(dstData[0])<<"    "<<"dstStep:"<< dstStep << endl;
	cout << "sizeof(srcData[0]):" << sizeof(srcData[0]) <<"    "<<"srcStep:"<< srcStep <<endl;

	
	for (int j = 0; j < src.cols; j++)
	{
		for (int i = 0; i < src.rows; i++)
		{
			double b = *(srcData + src.step*i + src.channels() * j + 0) / 255.0;
			double g = *(srcData + src.step*i + src.channels() * j + 1) / 255.0;
			double r = *(srcData + src.step*i + src.channels() * j + 2) / 255.0;

			*(dstData + dstStep*i + dst.channels()*j) = (b + g + r) / 3;
		}
	}
	cv::imshow("image", dst);
	waitKey();
}

代码运行结果:

Ref:

1、https://blog.csdn.net/dcrmg/article/details/52294259(Opencv Mat矩阵中data、size、depth、elemSize、step等属性的理解

2、https://blog.csdn.net/qianqing13579/article/details/45318279(OpenCV中Mat属性step,size,step1,elemSize,elemSize1

3、https://blog.csdn.net/lanmeng_smile/article/details/47864615(opencv的Mat中step

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值