OpenCV4 C++ 3.图像对象的创建与赋值

3.图像对象的创建与赋值

在这里插入图片描述

cv::Mat src = cv::imread("E:/Softwares/OpenCV_Study/lena.png", cv::IMREAD_UNCHANGED);
cv::Mat m1 = src.clone();	// 创建方法-克隆	创建了src的一个完全独立的副本,并将其存储到名为m1的cv::Mat对象中。

cv::Mat m2;
src.copyTo(m2);				// 将src的内容复制到了一个新的cv::Mat对象m2中

cv::Mat m3 = src;			// 赋值法	将src的引用赋给了m3,这意味着m3和src指向相同的数据,修改其中一个会影响另一个

cv::Mat m4 = cv::Mat::zeros(src.size(), src.type());		// 创建和src相同尺寸和通道数的全零矩阵
cv::Mat m5 = cv::Mat::zeros(cv::Size(512, 512), CV_8UC3);	// 创建尺寸为512x512、三通道的全零矩阵
cv::Mat m6 = cv::Mat::ones(cv::Size(512, 512), CV_8UC3);	// 创建尺寸为512x512、三通道的全一矩阵

cv::Mat kernel = (cv::Mat_<char>(3, 3) << 0, -1,  0,		// 创建3x3的矩阵作为图像卷积核
								      -1,  5, -1,
									   0, -1,  0);

clone()copyTo()都是深拷贝,它们创建了源cv::Mat对象的完全独立副本,即新的对象拥有自己的内存空间,而不是简单地共享源对象的数据。

区别在于:

  • clone()cv::Mat类的成员函数,它创建一个新的cv::Mat对象,并将源对象的数据复制到新对象中。它的语法是src.clone(),返回一个新的cv::Mat对象。
  • copyTo()cv::Mat类的成员函数,用于将源cv::Mat对象的数据复制到另一个已经创建好的cv::Mat对象中。它的语法是src.copyTo(dst),其中dst是已经创建好的目标cv::Mat对象。copyTo()还允许在复制过程中进行类型转换和区域选择等操作。

而直接使用赋值操作符(=)时,只是简单地将源对象的指针或引用赋给了目标对象,它们指向相同的数据。这意味着修改其中一个对象的内容将会影响到另一个对象,因为它们共享相同的数据存储空间。

CV_8UC3是OpenCV中用于表示图像数据类型的一种标记。这个标记通常用于指定图像的数据类型,其中:

  • CV_8UC3表示图像每个通道都是8位无符号的,且有三个通道,即每个像素由三个8位无符号整数组成,通常用于表示彩色图像。
  • C3表示图像是三通道的,即每个像素有三个分量(通道):蓝色(Blue)、绿色(Green)和红色(Red)。

因此,CV_8UC3表示每个像素由三个8位无符号整数组成,用于表示彩色图像。

这个标记通常在创建新的cv::Mat对象时用于指定图像的数据类型,例如:

cv::Mat image(Size(width, height), CV_8UC3);

这样就创建了一个宽度为width,高度为height的彩色图像,每个像素由三个8位无符号整数组成。

在示例代码中cv::Mat kernel可以用于创建卷积核,它是一个二维数组,用于图像处理中的卷积操作。卷积核的数值决定了在卷积过程中每个像素周围的加权求和方式,从而实现不同的图像处理效果。这个卷积核是一个3x3的矩阵,用于对图像进行锐化处理。在这个卷积核中,中心像素的权重为5,周围像素的权重为-1,通过对图像进行卷积操作,可以增强图像中的边缘信息。

cv::Mat m3 = cv::Mat::zeros(cv::Size(8, 8), CV_8UC1);
std::cout << m3 << std::endl;

这行代码创建了一个8x8大小的单通道(灰度)图像,每个像素由一个8位无符号整数(uchar)表示。因为它是单通道的,所以每个像素只包含灰度信息,范围从0到255。

  • 运行结果:

    在这里插入图片描述

cv::Mat m3 = cv::Mat::zeros(cv::Size(8, 8), CV_8UC3);
std::cout << m3 << std::endl;
  • 运行结果:

    在这里插入图片描述

这行代码创建了一个8x8大小的三通道图像,每个通道由一个8位无符号整数(uchar)表示。这种类型的图像通常用于表示彩色图像,每个像素有红、绿、蓝三个通道的信息。每个通道的范围仍然是0到255。

因此,这两个cv::Mat对象的主要区别在于通道数的不同。第一个只有一个通道,而第二个有三个通道,分别对应于彩色图像中的红、绿、蓝三种颜色通道。

cv::Mat m3 = cv::Mat::zeros(cv::Size(8, 8), CV_8UC3);
std::cout << "width: " << m3.cols << std::endl;				// 8
std::cout << "height: " << m3.rows << std::endl;			// 8
std::cout << "channels: " << m3.channels() << std::endl;	 // 3
  • 这段代码中的m3.cols返回图像的宽度,即8;m3.rows返回图像的高度,也是8;m3.channels()返回图像的通道数,即3。
cv::Mat m3 = cv::Mat::ones(cv::Size(8, 8), CV_8UC1);
std::cout << "width: " << m3.cols << std::endl;				// 8
std::cout << "height: " << m3.rows << std::endl;			// 8
std::cout << "channels: " << m3.channels() << std::endl;	 // 1
std::cout << m3 << std::endl;
  • 这段代码因为是单通道图像,所以输出的矩阵是一个以分号和空格分隔的8x8矩阵,每个元素值都是1。
cv::Mat m3 = cv::Mat::ones(cv::Size(8, 8), CV_8UC3);
  • 以上代码尤其需要注意的是cv::Mat::ones()函数会创建一个所有像素值都为1的图像,但是在三通道图像中,使用参数CV_8UC3,每个像素的通道值将会是[1, 0, 0],因为ones函数只设置了第一个通道为1,而其他两个通道为默认值0。
cv::Mat m3 = cv::Mat::zeros(cv::Size(8, 8), CV_8UC3);
m3 = 127;
std::cout << m3 << std::endl;
  • 这段代码创建了一个8x8大小的三通道图像,初始值为全零(即[0, 0, 0])。然后,将整个图像矩阵设置为了127。在这种情况下,每个像素的每个通道都会被设置为127,因为将一个标量值赋给了整个cv::Mat对象

  • 运行结果:

    在这里插入图片描述

  • 那么问题来了,想要将三个通道都变为直接值该如何操作

cv::Mat m3 = cv::Mat::zeros(cv::Size(8, 8), CV_8UC3);
m3 = cv::Scalar(127, 127, 127);
  • 运行结果:

    在这里插入图片描述

  • cv::Scalar(127, 127, 127) 创建了一个 cv::Scalar 对象,其中包含了三个值,分别是 127,127 和 127。在 OpenCV 中,cv::Scalar 主要用于表示颜色值,其中的三个值分别对应于bgr三个颜色通道(蓝色、绿色、红色),也可以表示其他的多通道数据。

    在这这段代码中,cv::Scalar(127, 127, 127) 可以表示一个灰度颜色,其中每个颜色通道的值都是 127。在设置图像的像素值时,可以使用 cv::Scalar 对象来指定颜色值,以方便处理不同通道数的情况。

cv::Mat m3 = cv::Mat::zeros(cv::Size(512, 512), CV_8UC3);
m3 = cv::Scalar(127, 127, 127);
std::cout << "width: " << m3.cols << std::endl;
std::cout << "height: " << m3.rows << std::endl;
std::cout << "channels: " << m3.channels() << std::endl;
std::cout << m3 << std::endl;
cv::imshow("create mat", m3);
  • 运行结果:

    在这里插入图片描述

  • 这段代码首先创建了一个大小为512x512的三通道图像 m3,初始值为全黑色,然后将整个图像矩阵设置为灰度值为127的灰色,每个通道的值都是127。接着,代码输出了图像的宽度、高度和通道数,并打印了图像的像素值。最后,使用 cv::imshow() 函数显示了创建的图像。这个代码段的输出结果应该是图像的宽度为512,高度为512,通道数为3(表示三通道图像),并且图像呈现出灰度值为127的灰色。

  • IO 操作通常是相对较慢的,因此在实际的程序中,尽量减少不必要的 IO 操作是一个很好的做法。在调试阶段,输出一些重要的信息来验证程序的正确性是有意义的,但在生产环境中,应该尽可能地减少不必要的输出操作,以提高程序的执行效率。在上述示例中,如果不需要实时查看图像,可以将 cv::imshow() 函数调用移除,这样可以减少不必要的图像显示操作,提高程序的执行效率。

cv::Mat m3 = cv::Mat::zeros(cv::Size(300, 300), CV_8UC3);
m3 = cv::Scalar(255, 0, 0);
std::cout << "width: " << m3.cols << std::endl;
std::cout << "height: " << m3.rows << std::endl;
std::cout << "channels: " << m3.channels() << std::endl;
std::cout << m3 << std::endl;
cv::imshow("blue mat", m3);
  • 这段代码创建了一个大小为300x300的三通道图像 m3,初始值为全黑色。然后,将整个图像矩阵设置为蓝色,即每个像素的通道值为 [255, 0, 0]。接着,代码输出了图像的宽度、高度和通道数,并打印了图像的像素值。最后,使用 cv::imshow() 函数显示了创建的蓝色图像。这个代码段的输出结果应该是图像的宽度为300,高度为300,通道数为3(表示三通道图像),并且图像呈现出蓝色。

  • 通过以上两种示例得知使用 cv::Mat::zeros() 函数可以创建一个全黑的图像,然后使用 cv::Scalar() 函数来赋予不同的颜色。这种方法可以创建不同颜色的图像,具体的颜色由 cv::Scalar() 函数的参数确定,分别对应蓝、绿、红三个通道的值。

    例如,要创建一个红色的图像,可以将 cv::Scalar() 的参数设置为 (0, 0, 255),表示红色通道值为255,而绿色和蓝色通道的值为0。类似地,可以根据需要创建其他颜色的图像。

综合示例:

cv::Mat m3 = cv::Mat::zeros(cv::Size(300, 300), CV_8UC3);
m3 = cv::Scalar(255, 0, 0);
std::cout << "width: " << m3.cols << std::endl;
std::cout << "height: " << m3.rows << std::endl;
std::cout << "channels: " << m3.channels() << std::endl;
cv::Mat m4 = m3;
m4 = cv::Scalar(0, 0, 255);
cv::imshow("mat", m3);
  • 运行结果:

    在这里插入图片描述

cv::Mat m3 = cv::Mat::zeros(cv::Size(300, 300), CV_8UC3);
m3 = cv::Scalar(255, 0, 0);
std::cout << "width: " << m3.cols << std::endl;
std::cout << "height: " << m3.rows << std::endl;
std::cout << "channels: " << m3.channels() << std::endl;

cv::Mat m4 = m3.clone();		// 深拷贝
m4 = cv::Scalar(0, 0, 255);
cv::imshow("mat m3", m3);
cv::imshow("mat m4", m4);
cv::Mat m3 = cv::Mat::zeros(cv::Size(300, 300), CV_8UC3);
m3 = cv::Scalar(255, 0, 0);
std::cout << "width: " << m3.cols << std::endl;
std::cout << "height: " << m3.rows << std::endl;
std::cout << "channels: " << m3.channels() << std::endl;

cv::Mat m4;
m3.copyTo(m4);				// 深拷贝
m4 = cv::Scalar(0, 0, 255);
cv::imshow("mat m3", m3);
cv::imshow("mat m4", m4);
  • 以上两段代码会产生同样的运行效果:

    在这里插入图片描述

  • 以上两段代码都是创建了两个 cv::Mat 对象 m3m4,并设置它们的像素值。主要的区别在于深拷贝的使用。

    第一段代码中,使用了 m4 = m3.clone() 进行深拷贝,确保了 m4m3 是完全独立的对象,因此修改 m4 的值不会影响到 m3,反之亦然。

    而第二段代码中,使用了 m3.copyTo(m4) 进行深拷贝,同样也确保了 m4m3 是完全独立的对象,因此修改 m4 的值不会影响到 m3,反之亦然。

    总结起来,这两段代码都创建了两个相同的图像对象,然后对其中一个对象进行了深拷贝,确保了它们的独立性,从而可以对它们进行不同的操作而不会相互影响。

  • 50
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值