[OpenCV]数字图像处理C++学习——03Mat对象附完整代码(小白入门篇)

前言

​ 在数字图像处理中,OpenCV 是一个强大的工具库,它为开发者提供了丰富的功能来操作和处理图像数据。作为初学者,掌握 OpenCV 中的基础概念和常用类是非常重要的,而 cv::Mat 对象作为 OpenCV 的核心类,是进行图像处理工作的基础。在这篇博客中,我们将从小白的角度出发,详细介绍 cv::Mat 对象的常用方法及其应用场景,辅以完整的 C++ 代码示例,快速入门 OpenCV 的图像处理。无论你是希望进行简单的图像读取和显示,还是希望掌握更复杂的图像变换与滤波操作,这篇文章都将为你打下坚实的基础。

什么是Mat类?

​ Mat类分为矩阵头指向存储数据的矩阵指针。矩阵头中包含矩阵的尺寸、存储方法、地址和引用次数等,只存放这几个固定的数据类型,所以矩阵头所占空间是固定的。图像复制和传递过程中主要的开销是存放矩阵数据。

(1)图像数据类型

数据类型通道位数描述
CV_8UC18 位单通道灰度图,8 位无符号整数
CV_8UC38 位三通道彩色图(BGR),8 位无符号整数
CV_16UC116 位单通道灰度图,16 位无符号整数
CV_16SC116 位单通道灰度图,16 位有符号整数
CV_32FC132 位单通道图像,32 位浮点数
CV_32FC332 位三通道图像,32 位浮点数

图像数据类型的选择取决于像素深度和通道数,最常见的类型包括 CV_8UC1(单通道灰度图)、CV_8UC3(三通道彩色图)、CV_16UC1(16 位无符号灰度图)、CV_16SC1(16 位有符号灰度图)、CV_32FC1CV_32FC3(分别为单通道和三通道的 32 位浮点图像)。

1.创建 Mat对象

先读取图像用于后面的操作

图片链接实验图片下载链接

    Mat src;
    src = cv::imread("sherlock.jpg");
    Mat image;
    image = cv::imread("sherlock.jpg");
    if (src.empty())
    {
        cout << "could not load image..." << endl;
        return;
    }
    namedWindow("input iamge", cv::WINDOW_AUTOSIZE);
    cv::imshow("input iamge", src);

cv::Mat 对象,可以是空的,也可以是预定义大小和类型的图像或矩阵。通过使用不同的构造函数和函数(如 zerosoneseye),你可以生成特定类型的矩阵。

    // 创建一个空的 Mat 对象
    cv::Mat mat1;
    // 创建一个 3x3 单通道的 8位图像(灰度图)
    cv::Mat mat2(3, 3, CV_8UC1, cv::Scalar(0));
    // 创建一个 3x3 三通道的图像(彩色图)
    cv::Mat mat3(3, 3, CV_8UC3, cv::Scalar(255, 0, 0));
    // 使用 `zeros`, `ones`, `eye` 函数创建特殊矩阵
    cv::Mat mat4 = cv::Mat::zeros(3, 3, CV_8UC1);  // 全零矩阵
    cv::Mat mat5 = cv::Mat::ones(3, 3, CV_8UC1);   // 全一矩阵
    cv::Mat mat6 = cv::Mat::eye(3, 3, CV_8UC1);    // 单位矩阵

2. 访问和修改像素值

at 方法可以用于获取或设置某个像素的值。对于灰度图像,你可以直接访问单个通道的值;对于彩色图像,可以分别访问 BGR 三个通道的值。

	//访问单个像素(灰度图)
	uchar pixelValue = src.at<uchar>(0, 0);
	//访问和修改单个像素(彩色图像)
	cv::Vec3b& color = src.at<cv::Vec3b>(0, 0);
	uchar blue = color[0];
	uchar green = color[1];
	uchar red = color[2];
	// 修改像素值
	src.at<cv::Vec3b>(0, 0) = cv::Vec3b(255, 255, 255);  // 将像素设为白色

3.图像的复制、截取和拼接

clone 方法用于深度复制图像,Rect 用于定义感兴趣区域 (ROI),而 hconcatvconcat 则分别用于水平和垂直拼接图像。

	//图像克隆拼接
	Mat dst1, dst2;
	dst1 = src.clone();
	namedWindow("copyimage1", cv::WINDOW_AUTOSIZE);
	cv::imshow("copyimage1", dst1);
	src.copyTo(dst2);
	namedWindow("copyimage2", cv::WINDOW_AUTOSIZE);
	cv::imshow("copyimage2", dst2);
	//图像截取
	cv::Rect roi(400, 50, 400, 400);  // (x,y,w,h)左上角起始点(x,y),截取范围宽高(h,w)
	cv::Mat croppedImage = dst1(roi);
	namedWindow("croppedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("croppedImage", croppedImage);
	//图像拼接
	// 水平拼接
	cv::Mat imageCopy = image.clone();
	cv::Mat hConcat;
	cv::hconcat(image,imageCopy,hConcat);
	namedWindow("hConcat", cv::WINDOW_AUTOSIZE);
	cv::imshow("hConcat", hConcat);
	//垂直拼接
	cv::Mat vConcat;
	cv::vconcat(image, imageCopy, vConcat);
	namedWindow("vConcat", cv::WINDOW_AUTOSIZE);
	cv::imshow("vConcat", vConcat);

水平拼接 result
在这里插入图片描述

4.图像转换(灰度、HSV转换)

在不同颜色空间之间通过cvtColor进行转换常见的转换如 BGR 到灰度图、HSV 等。

	Mat grayimage, hsvimage;
	cvtColor(src, grayimage, cv::COLOR_BGR2GRAY);  //灰度图
	cvtColor(src, hsvimage, cv::COLOR_BGR2HSV);    //HSV图
	namedWindow("grayimage", cv::WINDOW_AUTOSIZE);
	cv::imshow("grayimage", grayimage);
	namedWindow("hsvimage", cv::WINDOW_AUTOSIZE);
    cv::imshow("hsvimage", hsvimage);

HSVimage result
在这里插入图片描述

5.图像尺寸、通道数、数据类型等信息

获取图像的基本属性,如尺寸、通道数和数据类型,可以帮助动态调整图像处理方式。

	int cols = dst1.cols;   //行数
	int rows = dst1.rows;   //列数
	int channels = dst1.channels();  //通道数
	int type = dst1.type();          //数据类型
	printf("cols: %d rows: %d\n", cols, rows);
	printf("图像通道数:%d\n", channels);
	printf("数据类型:%d\n", type);

result
在这里插入图片描述

6.图像滤波(模糊处理)

滤波是图像处理中常见的操作,主要用于去除噪声或平滑图像。这是常用的几种滤波操作:平均模糊、高斯模糊和中值模糊。

	/******************图像滤波(模糊处理)***********************/
	cv::Mat blurredImage1, blurredImage2, blurredImage3;
	cv::blur(image, blurredImage1, cv::Size(5, 5)); //平均模糊
	cv::GaussianBlur(image, blurredImage2, cv::Size(5, 5), 0); //高斯模糊
	cv::medianBlur(image, blurredImage3, 5);  // 中值模糊
	namedWindow("平均模糊", cv::WINDOW_AUTOSIZE); // 显示平均模糊图像
	cv::imshow("平均模糊", blurredImage1);

7.图像算术运算

OpenCV上直接对图像进行加、减、乘、除等操作,实现图像的亮度调节、图像融合等操作。

	/******************图像算术运算***********************/
	cv::Mat result;
	// 图像加法
	cv::add(image, imageCopy, result);
	namedWindow("addmage", cv::WINDOW_AUTOSIZE);
	cv::imshow("addmage", result);
	// 图像减法
	cv::subtract(image, imageCopy, result);
	// 图像乘法(标量乘法)
	cv::multiply(image, 2.0, result);
	// 图像除法
	cv::divide(image, 2.0, result);

add result 明显感觉图像变亮

在这里插入图片描述

8.阈值处理

阈值处理是将图像中的像素值分为两类,通常用于图像的二值化。通过设置一个阈值,图像中大于该值的像素会被设置为最大值(通常是白色),而小于该值的像素会被设置为最小值(通常是黑色)。

	cv::Mat binaryImage;
	cv::threshold(grayimage, binaryImage, 128, 255, cv::THRESH_BINARY);
	namedWindow("binaryImage", cv::WINDOW_AUTOSIZE); //show image
	cv::imshow("binaryImage", binaryImage);

binaryImage result
在这里插入图片描述

9.边缘检测

Canny 边缘检测是一种常用的边缘检测算法,它能够有效地检测出图像中的边缘,并且具有良好的抗噪声性能。

	/******************边缘检测***********************/
	cv::Mat edges;
	cv::Canny(grayimage, edges, 50, 150); //双阈值方法
	namedWindow("edges", cv::WINDOW_AUTOSIZE);
	cv::imshow("edges", edges);

edges result
在这里插入图片描述

10.图像变换(缩放、旋转、翻转)

resize 用于调整图像的大小,getRotationMatrix2DwarpAffine 结合用于旋转图像,flip 用于翻转图像(水平或垂直)。

	/******************图像变换(缩放、旋转、翻转)***********************/
	cv::Mat resizedImage, rotatedImage, flippedImage;
	// 缩放图像
	cv::resize(image, resizedImage, cv::Size(100, 100));
	namedWindow("resizedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("resizedImage", resizedImage);
	// 旋转图像
	cv::Point2f center(image.cols / 2.0, image.rows / 2.0); //旋转中心点
	cv::Mat rotMatrix = cv::getRotationMatrix2D(center, 45, 1.0);//中心点、角度、缩放因子
	cv::warpAffine(image, rotatedImage, rotMatrix, image.size());
	namedWindow("rotatedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("rotatedImage", rotatedImage);
	// 翻转图像
	cv::flip(image, flippedImage, 1);  // 水平翻转
	namedWindow("flippedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("flippedImage", flippedImage);

rotatedImage result
在这里插入图片描述

完整代码

#include<opencv2/opencv.hpp>
#include<highgui.hpp>
using namespace cv;
using namespace std;

void mat_learn()
{
	//input image
	Mat src;
	src = cv::imread("sherlock.jpg");
	Mat image;
	image = cv::imread("sherlock.jpg");
	if (src.empty())
	{
		cout << "could not load image..." << endl;
		return;
	}
	namedWindow("input iamge", cv::WINDOW_AUTOSIZE);
	cv::imshow("input iamge", src);
	/******************创建Mat对象***********************/
	// 创建一个空的 Mat 对象
	cv::Mat mat1;
	// 创建一个 3x3 单通道的 8位图像(灰度图)
	cv::Mat mat2(3, 3, CV_8UC1, cv::Scalar(0));
	// 创建一个 3x3 三通道的图像(彩色图)
	cv::Mat mat3(3, 3, CV_8UC3, cv::Scalar(255, 0, 0));
	// 使用 `zeros`, `ones`, `eye` 函数创建特殊矩阵
	cv::Mat mat4 = cv::Mat::zeros(3, 3, CV_8UC1);  // 全零矩阵
	cv::Mat mat5 = cv::Mat::ones(3, 3, CV_8UC1);   // 全一矩阵
	cv::Mat mat6 = cv::Mat::eye(3, 3, CV_8UC1);    // 单位矩阵

	/******************访问和修改像素值***********************/
	//访问单个像素(灰度图)
	uchar pixelValue = src.at<uchar>(0, 0);
	//访问和修改单个像素(彩色图像)
	cv::Vec3b& color = src.at<cv::Vec3b>(0, 0);
	uchar blue = color[0];
	uchar green = color[1];
	uchar red = color[2];
	// 修改像素值
	src.at<cv::Vec3b>(0, 0) = cv::Vec3b(255, 255, 255);  // 将像素设为白色

	//创建一张空白图像
	Mat dst;
	dst = Mat(src.size(), src.type());
	dst = Scalar(0, 0, 255); // 红色
	namedWindow("outimage", cv::WINDOW_AUTOSIZE);
	cv::imshow("outimage", dst);
	
	/******************图像的复制、截取和拼接***********************/
	//图像克隆拼接
	Mat dst1, dst2;
	dst1 = src.clone();
	namedWindow("copyimage1", cv::WINDOW_AUTOSIZE);
	cv::imshow("copyimage1", dst1);
	src.copyTo(dst2);
	namedWindow("copyimage2", cv::WINDOW_AUTOSIZE);
	cv::imshow("copyimage2", dst2);
	//图像截取
	cv::Rect roi(400, 50, 400, 400);  // (x,y,w,h)左上角起始点(x,y),截取范围宽高(h,w)
	cv::Mat croppedImage = dst1(roi);
	namedWindow("croppedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("croppedImage", croppedImage);
	//图像拼接
	// 水平拼接
	cv::Mat imageCopy = image.clone();
	cv::Mat hConcat;
	cv::hconcat(image,imageCopy,hConcat);
	namedWindow("hConcat", cv::WINDOW_AUTOSIZE);
	cv::imshow("hConcat", hConcat);
	//垂直拼接
	cv::Mat vConcat;
	cv::vconcat(image, imageCopy, vConcat);
	namedWindow("vConcat", cv::WINDOW_AUTOSIZE);
	cv::imshow("vConcat", vConcat);

	/******************图像转换(灰度、HSV转换)***********************/
	Mat grayimage, hsvimage;
	cvtColor(src, grayimage, cv::COLOR_BGR2GRAY);  //灰度图
	cvtColor(src, hsvimage, cv::COLOR_BGR2HSV);    //HSV图
	namedWindow("grayimage", cv::WINDOW_AUTOSIZE);
	cv::imshow("grayimage", grayimage);

	namedWindow("hsvimage", cv::WINDOW_AUTOSIZE);
	cv::imshow("hsvimage", hsvimage);
	printf("iamge channels: %d\n", src.channels());
	printf("grayimage channels: %d\n", grayimage.channels());

	/******************图像尺寸、通道数、数据类型等信息***********************/
	int cols = dst1.cols;   //行数
	int rows = dst1.rows;   //列数
	int channels = dst1.channels();  //通道数
	int type = dst1.type();          //数据类型
	printf("cols: %d rows: %d\n", cols, rows);
	printf("图像通道数:%d\n", channels);
	printf("数据类型:%d\n", type);

	/******************图像滤波(模糊处理)***********************/
	cv::Mat blurredImage1, blurredImage2, blurredImage3;
	cv::blur(image, blurredImage1, cv::Size(5, 5)); //平均模糊
	namedWindow("平均模糊", cv::WINDOW_AUTOSIZE);
	cv::imshow("平均模糊", blurredImage1);
	cv::GaussianBlur(image, blurredImage2, cv::Size(5, 5), 0); //高斯模糊
	cv::medianBlur(image, blurredImage3, 5);  // 中值模糊
	/******************图像算术运算***********************/
	cv::Mat result;
	// 图像加法
	cv::add(image, imageCopy, result);
	namedWindow("addmage", cv::WINDOW_AUTOSIZE);
	cv::imshow("addmage", result);
	// 图像减法
	cv::subtract(image, imageCopy, result);
	// 图像乘法(标量乘法)
	cv::multiply(image, 2.0, result);
	// 图像除法
	cv::divide(image, 2.0, result);

	/******************阈值处理***********************/
	cv::Mat binaryImage;
	cv::threshold(grayimage, binaryImage, 128, 255, cv::THRESH_BINARY);
	namedWindow("binaryImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("binaryImage", binaryImage);
	/******************边缘检测***********************/
	cv::Mat edges;
	cv::Canny(grayimage, edges, 50, 150);
	namedWindow("edges", cv::WINDOW_AUTOSIZE);
	cv::imshow("edges", edges);

	/******************图像变换(缩放、旋转、翻转)***********************/
	cv::Mat resizedImage, rotatedImage, flippedImage;
	// 缩放图像
	cv::resize(image, resizedImage, cv::Size(100, 100));
	namedWindow("resizedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("resizedImage", resizedImage);
	// 旋转图像
	cv::Point2f center(image.cols / 2.0, image.rows / 2.0);
	cv::Mat rotMatrix = cv::getRotationMatrix2D(center, 45, 1.0);
	cv::warpAffine(image, rotatedImage, rotMatrix, image.size());
	namedWindow("rotatedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("rotatedImage", rotatedImage);
	// 翻转图像
	cv::flip(image, flippedImage, 1);  // 水平翻转
	namedWindow("flippedImage", cv::WINDOW_AUTOSIZE);
	cv::imshow("flippedImage", flippedImage);

	waitKey(0);
}
int main() 
{
	mat_learn();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mirror_zAI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值