头文件:
定义了图像数据结构的核心头文件和包含了所有图形接口函数的 highgui 头文件:

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
cv::Mat image; // 创建一个空图像
//这个定义创建了一个尺寸为 0×0 的图像,
//可以通过访问 cv::Mat 的 size 属性来验证这一点:
image= cv::imread("puppy.bmp"); // 读取输入图像

图像行数:image.rows 图像列数:image.cols 检查图像是否读入:

if (image.empty()) { 
// 未创建图像……
// 并退出程序
...
}

如果没有分配图像数据, empty 方法将返回 true。

// 定义窗口(可选)
cv::namedWindow("Original Image");
// 显示图像
cv::imshow("Original Image", image);

水平翻转图像的简单函数:flip

cv::Mat result; // 创建另一个空的图像
cv::flip(image,result,1); 
// 正数表示水平
// 0 表示垂直
// 负数表示水平和垂直
在另一个窗口显示结果:
cv::namedWindow("Output Image"); // 输出窗口
cv::imshow("Output Image", result);

等待函数:cv::waitKey(0); // 0 表示永远地等待按键 // 键入的正数表示等待的毫秒数 保存图像:cv::imwrite("output.bmp", result); // 保存结果

imread函数可以直接导入一张灰色图像。

// 读入一个图像文件并将其转换为灰度图像
image= cv::imread("puppy.bmp", CV::IMREAD_GRAYSCALE);
// 读取图像,并将其转换为三通道彩色图像
image= cv::imread("puppy.bmp", CV::IMREAD_COLOR);

在这样创建的图像中,每个像素有 3 字节, OpenCV 中用 CV_8UC3 表示。当然了,如果输入的图像文件是灰度图像,这三个通道的值就是相同的。

通道数:image.channels()

当你用 imshow 显示由整数( CV_16U 表示 16 位无符号整数, CV_32S 表示 32 位有符号整数)构成的图像时,图像每个像素的值会被除以 256,以便能够在 256 级灰度中显示。同样,在显示由浮点数构成的图像时,值的范围会被假设为 0.0(显示黑色) ~1.0(显示白色)。超出这个范围的值会显示为白色(大于 1.0 的值)或黑色(小于 0.0 的值)。

1图像上点击,需要重新学

在这里插入代码片
  1. 在图像上绘图
cv::putText(image, // 目标图像
"This is a dog.", // 文本
cv::Point(40,200), // 文本位置
cv::FONT_HERSHEY_PLAIN, // 字体类型
2.0, // 字体大小
255, // 字体颜色(这里用白色)
2); // 文本厚度

画⚪

cv::circle(image, // 目标图像
cv::Point(155,110), // 中心点坐标
65, // 半径
0, // 颜色(这里用黑色)
3); // 厚度

基本的形状绘制函数有 circle、 ellipse、 line 和 rectangle。

深入了解 cv::Mat

// 创建一个 240 行×320 列的新图像
cv::Mat image1(240,320,CV_8U,100);//CV_8UC1都是代表单通道

我们需要指定每个矩阵元素的类型,这里用 CV_8U 表示每个像素对应 1 字节(灰度图像),用字母 U 表示无符号;你也可用字母 S 表示有符号。对于彩色图像,你应该用三通道类型( CV_8UC3),也可以定义 16 位和 32 位的整数(有符号或无符号),例如 CV_16SC3。我们甚至可以使用 32 位和 64 位的浮点数(例如 CV_32F)。

图像(或矩阵)的每个元素都可以包含多个值(例如彩色图像中的三个通道),因此 OpenCV引入了一个简单的数据结构 cv::Scalar,用于在调用函数时传递像素值。该结构通常包含一个或三个值。如果要创建一个彩色图像并用红色像素初始化,可用如下代码:

// 创建一个红色图像
// 通道次序是 BGR
cv::Mat image2(240,320,CV_8UC3,cv::Scalar(0,0,255));
与之类似,初始化灰度图像可这样使用这个数据结构: cv::Scalar(100)
// 创建一个未初始化的彩色图像
cv::Mat image2(cv::Size(320,240),CV_8UC3);

总结:如何创建图像

cv::Mat image2(cv::size(100,100),......)
cv::Mat image2(100,100,.....);//和上一个一样
cv::Mat image2(.....,cv::scalar(0,0,255))
cv::Mat image2(.....,0,0,255)//和上一个效果一样
CV8U=CV8UC1//代表单通道
// 所有图像都指向同一个数据块
cv::Mat image4(image3);
image1= image3;

这些是浅复制,改变 image1的值 会影响image3

// 这些图像是原始图像的新副本
image3.copyTo(image2);
cv::Mat image5= image3.clone();

深复制,改变image2,不影响 image3

如果你需要把一幅图像复制到另一幅图像中,且两者的数据类型不一定相同,那就要使用convertTo 方法了:

```cpp
关于opencv中的浅拷贝与深拷贝大家众所周知,这里先赘述一下

(1)浅拷贝:  

Mat B;  

B = image  // 第一种方式  

Mat C(image); // 第二种方式

这两种方式称为浅copy,是由于它们有不同的矩阵头,但是它们共享内存空间,即指向一个矩阵。当图像矩阵发生变化时,两者相关联,都会变化。

(2)深拷贝

Mat B,C;  

B = image.clone();       // 第一种方式  

image.copyTo(C); // 第二种方式  

深拷贝是真正的copy了一个新的图像矩阵,此时image,B,C三者相互没有影响
// 转换成浮点型图像[0,1]
image1.convertTo(image2,CV_32F,1/255.0,0.0);
注意的是,这两幅图像的通道数量必须相同
**处理小矩阵**


// // 3×3 双精度型矩阵
cv::Matx33d matrix(3.0, 2.0, 1.0,
2.0, 1.0, 3.0,
1.0, 2.0, 3.0);
// 3×1 矩阵(即向量)
cv::Matx31d vector(5.0, 1.0, 3.0);
// 相乘
cv::Matx31d result = matrix*vector;
这些矩阵可以进行常见的数学运算

定义感兴趣区域

cv::Mat imageROI(image,
cv::Rect(image.cols-logo.cols, // ROI 坐标
image.rows-logo.rows,
logo.cols,logo.rows)); // ROI 大小

注意:上个函数是浅复制
// 插入标志
logo.copyTo(imageROI);
ROI 还可以用行和列的值域来描述。值域是一个从开始索引到结束索引的连续序列(不含开
始值和结束值),可以用 cv::Range 结构来表示这个概念。因此,一个 ROI 可以用两个值域来
定义。本例中的 ROI 也可以定义为:
imageROI= image(cv::Range(image.rows-logo.rows,image.rows),
cv::Range(image.cols-logo.cols,image.cols));

MASK

// 在图像的右下角定义一个 ROI
imageROI= image(cv::Rect(image.cols-logo.cols,
image.rows-logo.rows,
logo.cols,logo.rows));
// 把标志作为掩码(必须是灰度图像)
cv::Mat mask(logo);
// 插入标志,只复制掩码不为 0 的位置
logo.copyTo(imageROI,mask);

opencv 4 计算机视觉 pdf opencv计算机视觉编程攻略_灰度图像