openCV Mat类及遍历像素点

源码:

void QuickDemo::CreateTest(Mat &image)
{
	Mat m1,m2,cvt;

	m1 = image;//image.clone();//克隆图像
	image.copyTo(m2);//复制image图像给m2

	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);//创建一个大小为8*8的图像,3个通道,并且全部赋值0;全部赋值1用ones
	m3 = Scalar(0,0,255);//对每个像素点按0,0,255赋值
	std::cout << "width" << m3.cols << "hight" << m3.rows << "channel" << m3.channels() << std::endl;//打印图像列行、通道
	std::cout << m3 << std::endl;//输出整个图形数据
	imshow("图像",m3);
}

1、Mat类

在定义Mat mx后,赋值图像可以使用克隆/复制的方法,
克隆:mx.clone()
复制:mx.copyTo(mat)
但是如果直接使用赋值时则不同,比如说

void QuickDemo::CreateTest(Mat &image)
{
	Mat m1, m2;

	m1 = Mat::zeros(Size(4, 4), CV_8UC3);
	std::cout << m1 << std::endl;
	
	m2 = m1;//直接赋值给m2
	m2 = Scalar(1,2,3);
	std::cout << "Scalar重新赋值" << std::endl;
	std::cout << m1 << std::endl;

	m2 = 255;
	std::cout << "m2 = 255" << std::endl;
	std::cout << m1 << std::endl;

	namedWindow("m1", WINDOW_FREERATIO);
	imshow("m1",m1);
}

那么会得到如下现象:

1、从现象可以看到,当m2 = m1时,其实是类似指针操作,共用同一片内存地址,所以出现更改m2数据会一影响m1的图像。
2、当直接对m2赋值数值255时会看到,它只对第一通道赋值,当CV_8UC3时值会出现赋值不完整现象,所以还是使用Scalar函数赋值比较妥当。
3、窗口显示的蓝色图像说明,我们常说的RGB在实际对应时数据为BGR

补充:创建相同大小类型的图像Mat m1 = Mat::zeros(image.size(), image.type());

2、遍历像素点:

分析像素点x,y

void QuickDemo::CreateTest(Mat &image)
{
	Mat m1;

	m1 = Mat::zeros(Size(4, 3), CV_8UC1);
	//m1 = Scalar(1,2,3);
	m1.at<uchar>(2, 0) = 2;
	std::cout << "col:" << m1.cols << "row:" << m1.rows << "channle:" << m1.channels() << std::endl;
	std::cout << m1 << std::endl;
}

该代码会得到如下结果:

依据现象可以看出,x对应col;y对应row;由于此为一个数组看时,即为m1[2][0] = 2
注意当图像为彩色时channels = 3,灰度 = 1
接着就可以真的开始遍历了
数组方式:image.at(row, col)
指针方式:uchar *p = image.ptr(row);

->1通过数组的方式访问:

void QuickDemo::CreateTest(Mat &image)
{
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();
	int col = 0, row = 0,i = 0;

	for (row = 0; row < h; row++)
	{
		for (col = 0; col < w; col++)
		{
			if (dims == 1)
			{
				image.at<uchar>(row, col) = 255 - image.at<uchar>(row, col);
			}
			else if (dims == 3)
			{
				for (i = 0; i < 3; i++)
				{
					//image.at<Vec3b>(row, col)[i] = 255 - image.at<Vec3b>(row, col)[i];	
					//等价于
					Vec3b bgr;
					bgr = image.at<Vec3b>(row, col);
					image.at<Vec3b>(row, col)[i] = 255 - bgr[i];
				}

			}
		}
	}
	imshow("图像取反",image);
}

->1通过指针的方式访问:

void QuickDemo::CreateTest(Mat &image)
{
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();
	int col = 0, row = 0,i = 0;
	uchar *p = NULL;

	for (row = 0; row < h; row++)
	{
		p = image.ptr<uchar>(row);
		for (col = 0; col < w; col++)
		{
			if (dims == 1)
			{
				*p = 255 - *p;
				p++;
			}
			else if (dims == 3)
			{
				for (i = 0; i < 3; i++)
				{
					*p = 255 - *p;
					p++;
				}

			}
		}
	}
	imshow("图像取反",image);
}

图像取反后的效果:

好了,到此就结束了

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2022年5月22日
下一篇 2022年5月22日

相关推荐