OPenCV直接提供常用的Mat类来存储矩阵类型,其中包括矩阵、向量、图像等数据信息。
Mat类由两部分组成:矩阵头和指向像素数据的矩阵指针
Mat类的创建
构造方法:
Mat mjpg(2,2,CV_8UC3,Scalar(0,0,255));
mjpg:Mat类型的变量
3,3:3行2列的矩阵
8U:表示8位无符号整数
C:表示通道数,比如C1表示一个通道的像素
Scalar:表示颜色,默认颜色顺序为(BGR)
浅拷贝
矩阵相互赋值,之创建矩阵头,共享数据部分
Mat mjpg(jpg);//jpg和mymat共享图像数据
Mat myJpg(mjpg);//创建头部分,共享数据部分
使用clone()/copyTo()实现深拷贝
clone 方法用于创建一个与原始图像或矩阵完全相同的副本。它会复制数据和元数据,并返回一个新的独立对象。
cv::Mat sourceImage = cv::imread("source.jpg");
cv::Mat clonedImage = sourceImage.clone();
clone方法执行的是浅拷贝,即复制图像或矩阵的头指针和元数据,而不是实际的像素数据。
copyTo 方法用于将一个图像或矩阵复制到另一个已经存在的目标图像或矩阵中。它允许你选择复制的区域和目标位置。
cv::Mat sourceImage = cv::imread("source.jpg");
cv::Mat targetImage = cv::Mat::zeros(sourceImage.size(), sourceImage.type());
sourceImage.copyTo(targetImage);
如果进行深拷贝并复制像素数据,可以结合使用 clone 和 copyTo 方法:
cv::Mat sourceImage = cv::imread("source.jpg");
cv::Mat clonedImage = sourceImage.clone();
cv::Mat deepCopiedImage;
clonedImage.copyTo(deepCopiedImage);
clone 方法创建了 sourceImage 的副本,并且随后的 copyTo 方法将副本的像素数据复制到 deepCopiedImage 中,实现了深拷贝。
读取图像函数:
imread(char filename,int flags);
常用标志位:
cv::IMREAD_UNCHANGED:读取图像的原始数据,包括 alpha 通道(如果图像有的话)。
cv::IMREAD_GRAYSCALE:读取灰度图像,将彩色图像转换为单通道灰度图像。
cv::IMREAD_COLOR:读取彩色图像,忽略 alpha 通道(如果图像有的话)。
cv::IMREAD_ANYDEPTH:读取 16 位或 32 位深度的图像,并将其保存为 16 位或 32 位深度的 Mat 对象。
cv::IMREAD_ANYCOLOR:读取任何颜色的图像,不进行颜色空间转换。
cv::IMREAD_LOAD_GDAL:使用 GDAL 库加载图像文件,支持多种文件格式,如 GeoTIFF、HDF5 等。
flags 参数还可以与以下标志组合使用:
cv::IMREAD_REDUCED_GRAYSCALE_2:读取灰度图像,并将其大小减小一半。
cv::IMREAD_REDUCED_GRAYSCALE_4:读取灰度图像,并将其大小减小四分之一。
cv::IMREAD_REDUCED_GRAYSCALE_8:读取灰度图像,并将其大小减小八分之一。
cv::IMREAD_REDUCED_COLOR_2:读取彩色图像,并将其大小减小一半。
cv::IMREAD_REDUCED_COLOR_4:读取彩色图像,并将其大小减小四分之一。
cv::IMREAD_REDUCED_COLOR_8:读取彩色图像,并将其大小减小八分之一。
显示图像函数
imshow(const String &winname, //窗口名称
InputArry mat //图像矩阵
);
写入图像
bool cv::imwrite(const String& filename, //存图像的文件名
InputArray img, //要保存的图像数据,填Mat类型的图像就行
const std::vector<int>& params = std::vector<int>() //params 是可选的保存参数
);
常用的 params 参数包括:
- cv::IMWRITE_JPEG_QUALITY:指定 JPEG 压缩的质量,范围从 0 到 100(默认值为 95)。
- cv::IMWRITE_PNG_COMPRESSION:指定 PNG 压缩的级别,范围从 0 到 9(默认值为 3)。
- cv::IMWRITE_WEBP_QUALITY:指定 WebP 压缩的质量,范围从 0 到 100(默认值为 80)。
- cv::IMWRITE_PAM_TUPLETYPE:指定 PAM 格式图片的色彩空间类型。
以下是一个示例,展示如何使用 imwrite 函数将图像保存为 JPEG 格式的文件:
cv::Mat image = cv::imread("image.jpg");
if (!image.empty()) {
bool result = cv::imwrite("output.jpg", image);
if (result) {
std::cout << "Image saved successfully." << std::endl;
} else {
std::cout << "Failed to save the image." << std::endl;
}
}
在此示例中,首先使用 imread 函数读取名为 “image.jpg” 的图像文件,并将其保存在 cv::Mat 类型的变量 image 中。然后,使用 imwrite 函数将 image 保存为名为 “output.jpg” 的 JPEG 格式文件。
图像绘制
1. 绘制直线
- cv::Point()
- cv::line()
#include <opencv2/opencv.hpp>
int main() {
// 创建一个空白图像
cv::Mat image = cv::Mat::zeros(400, 400, CV_8UC3);
// 定义直线的起点和终点
cv::Point start(50, 50);
cv::Point end(350, 350);
// 绘制直线,颜色为红色,线条宽度为2
cv::line(image, start, end, cv::Scalar(0, 0, 255), 2);
// 显示图像
cv::imshow("Line", image);
cv::waitKey(0);
return 0;
}
2. 绘制矩形
- cv::Rect()
- cv::recttangle()
void rectangle(InputOutputArray img, 输入输出图像,为要绘制矩形框的图像对象。
Point pt1, //矩形框左上角顶点的坐标
Point pt2, //矩形框右下角顶点的坐标
const Scalar& color, //矩形框的颜色,为 Scalar 类型,可使用 cv::Scalar() 函数创建。
int thickness = 1, //矩形框的线宽,默认为 1 像素
int lineType = LINE_8, //矩形框的线型,默认为 8 连通线型
int shift = 0 //矩形框的边界类型,默认为 0
);
注意,pt1 和 pt2 参数分别表示矩形框的左上角和右下角顶点的坐标,因此需要根据具体需求计算出这些坐标。
代码示例:
#include <opencv2/opencv.hpp>
int main() {
// 创建一个空白图像
cv::Mat image = cv::Mat::zeros(400, 400, CV_8UC3);
// 定义矩形的左上角和右下角顶点
cv::Point topLeft(50, 50);
cv::Point bottomRight(300, 200);
// 绘制矩形,颜色为绿色,线条宽度为3
cv::rectangle(image, topLeft, bottomRight, cv::Scalar(0, 255, 0), 3);
// 显示图像
cv::imshow("Rectangle", image);
cv::waitKey(0);
return 0;
}
3. 绘制圆形
相关函数:
void cv::circle(
cv::InputOutputArray img, //要绘制圆形的图像
cv::Point center, //圆心的坐标,可以使用 cv::Point(x, y) 来表示
int radius, //圆的半径
const cv::Scalar& color, //圆的颜色
int thickness = 1, //可选参数,指定圆的边界线条宽度,默认为1
int lineType = LINE_8, //选参数,指定线条的类型,默认为8-connected线条
int shift = 0 //可选参数,指定圆心坐标和半径的小数位数,默认为0。
);
代码示例:
#include <opencv2/opencv.hpp>
int main() {
// 创建一个空白图像
cv::Mat image = cv::Mat::zeros(400, 400, CV_8UC3);
// 定义圆心和半径
cv::Point center(200, 200);
int radius = 100;
// 绘制圆形,颜色为蓝色,线条宽度为2
cv::circle(image, center, radius, cv::Scalar(255, 0, 0), 2);
// 显示图像
cv::imshow("Circle", image);
cv::waitKey(0);
return 0;
}
4. 绘制椭圆
函数原型:
void cv::ellipse(
InputOutputArray img, //输入/输出图像
Point center, //椭圆的中心点坐标
Size axes, //椭圆的长轴和短轴长度
double angle, //椭圆旋转角度
double startAngle, //椭圆绘制的起始角度
double endAngle, //椭圆绘制的终止角度
const Scalar& color, //椭圆的颜色
int thickness = 1, //椭圆边界线条的宽度,默认为1
int lineType = LINE_8, //线条的类型,默认为 LINE_8
int shift = 0 //中心坐标和轴长度的小数位数,默认为0
);
代码示例:
#include <opencv2/opencv.hpp>
int main() {
cv::Mat image = cv::Mat::zeros(400, 400, CV_8UC3);
cv::Point center(200, 200);
cv::Size axes(100, 50); // 长轴为100,短轴为50
double angle = 30; // 旋转角度
cv::ellipse(image, center, axes, angle, 0, 360, cv::Scalar(0, 255, 0), 2);
cv::imshow("Ellipse", image);
cv::waitKey(0);
return 0;
}
5. 绘制多边形
函数原型:
void cv::polylines(
InputOutputArray img, //输入/输出图像
const Point* pts, //多边形顶点的数组
const int* npts, //每个多边形的顶点数的数组
int ncontours, //多边形的数量
bool isClosed, //表示多边形是否闭合的布尔值
const Scalar& color, //多边形的颜色
int thickness = 1, //多边形边界线条的宽度,默认为1
int lineType = LINE_8, //线条的类型,默认为 LINE_8
int shift = 0 //坐标位移的小数位数,默认为0
);
代码示例:
#include <opencv2/opencv.hpp>
int main() {
cv::Mat image = cv::Mat::zeros(400, 400, CV_8UC3);
cv::Point pts[4] = {cv::Point(50, 50), cv::Point(50, 200), cv::Point(200, 200), cv::Point(200, 50)};
const cv::Point* points[1] = {pts};
int npts[1] = {4};
int ncontours = 1;
bool isClosed = true;
cv::polylines(image, points, npts, ncontours, isClosed, cv::Scalar(255, 0, 0), 2);
cv::imshow("Polyline", image);
cv::waitKey(0);
return 0;
}
6.绘制文本
函数原型:
void putText(
cv::Mat& img, //要绘制文本的目标图像
const cv::String& text, //要绘制的文本字符串
cv::Point org, //文本左下角的起始坐标点,即文本的基线的左下角位置
int fontFace, //字体类型,可以使用 cv::HersheyFonts 中的常量值
double fontScale, //字体大小因子,控制文本的大小
cv::Scalar color, //文本颜色,使用 cv::Scalar(b, g, r) 格式表示颜色
int thickness = 1, //文本颜色,使用 cv::Scalar(b, g, r) 格式表示颜色,
int lineType = LINE_8, //文本的线型,可以是 LINE_8、LINE_4 等,决定文本边缘的平滑度。
bool bottomLeftOrigin = false //可选参数,默认为 false,即 org 参数表示文本左下角的位置。如果设置为 true,则 org 参数表示文本左上角的位置。
);
代码示例:
#include <opencv2/opencv.hpp>
int main() {
cv::Mat img = cv::imread("example.jpg");
if (img.empty()) {
std::cerr << "Failed to load image" << std::endl;
return -1;
}
cv::String text = "Hello, OpenCV!";
cv::Point org(50, 100); // 文本左下角的起始坐标
int fontFace = cv::FONT_HERSHEY_SIMPLEX;
double fontScale = 1.5;
cv::Scalar color(255, 0, 0); // 红色
int thickness = 2;
int lineType = cv::LINE_8;
cv::putText(img, text, org, fontFace, fontScale, color, thickness, lineType);
cv::imshow("Image with Text", img);
cv::waitKey(0);
return 0;
}