离职之际,自学一下图像相关的知识点,只是简单学了一点皮毛!
目录
官网下载链接:Releases - OpenCV

下载后双击开始解压安装



解压完毕

进入路径 D:\opencv\opencv\build\x64\vc14\bin

vs2019及其以上的版本可以选择vc15那个文件夹
拷贝该路径,设置环境变量

在路径D:\opencv\opencv\build\x64\vc14\lib 会有项目中需要使用到的lib

新建一个VS工程,
右键 属性 - VC++目录 - 包含库目录,添加头文件路径进来

右键 属性 - VC++目录 - 库目录,添加lib文件路径进行

右键 属性 - 链接器 - 输入 - 附加依赖项,将opencv_world460d.lib添加进来,如果是release项目,那么就添加opencv_world460.lib

注意,属性中的“配置”和“平台”需要和界面的保持一致

当然,上面添加目录和库目录的操作,可以将相应的头文件和库拷贝到项目路径,再添加项目路径进来即可!
编写如下代码测试环境:
- #include
-
- #include
- #include
-
-
- using namespace cv;
-
-
- void int test1(Mat src) {
-
- // 设置新的窗体标题,参数一窗体标题,参数二窗体随图片大小
- namedWindow("opencv窗口2", WINDOW_AUTOSIZE);
-
- Mat output_image;
- /* 设置图片颜色 */
- cvtColor(src, output_image, COLOR_BGRA2RGB);
- imshow("opencv窗口2", output_image);
-
- /* 保存图片到本地 */
- imwrite("D:/new.png", output_image);
-
- // 等待
- waitKey(0);
- }
-
-
- int main(void) {
-
- // 正常:IMREAD_COLOR
- // 灰度:IMREAD_GRAYSCALE
- Mat image = imread("图.jpeg", IMREAD_COLOR); // 读取一张图片
- if (image.empty()) { // 判断图片是否读取成功
- printf("path image NULL!\n");
- return -1;
- }
-
- // 显示图片 参数一是窗体标题,参数二图片对象
- imshow("原图", image);
-
-
- test1(image);
-
- return 0;
- }
编译运行,不出意外的话,就会显示两张我们指定路径读取的图片

左边那一种是修改颜色后的图片,右边是原图!
至此,环境搭建完毕!
1. imread
Mat image = imread("图.jpeg", IMREAD_COLOR);
解析:读取一张图片。
2. image.empty()
解析:判断文件是否读取成功,ture表示不成功,false表示成功。
3. imshow
imshow("opencv窗口2", output_image);
解析:显示一张图片,参数一是窗体名字,参数二是图片对象,也就是Mat对象
4. imwrite
imwrite("D:/new.png", output_image);
解析:将图像保存到本地。参数一是文件路径名,参数二是图片对象。
5. waitKey
int waitKey(int delay = 0);
解析:等待,相当于c/c++中的system("pause"); 参数为0,表示一直等待,其他大于零的数,则表示等待对应的秒数。
6. destroyAllWindows
void destroyAllWindows();
解析:销毁所有打开的窗体。
7. cvtColor
void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
解析:设置图像的颜色。参数一是输入图像对象,参数二是设置好输出的图像对象,参数三是设置图像颜色枚举(enum ColorConversionCodes)
8. clone
Mat src = image.clone()
解析:将图像对象克隆赋值,需要另一个Mat对象去接收,相当于深拷贝。
8. copyTo
- Mat m2;
- image.copyTo(m2)
解析:将图像对象拷贝给另一个图像对象,相当于深拷贝。
9. zeros
Mat m4 = Mat::zeros(Size(128, 128), CV_8UC3);
解析:创建空白图像。参数一是图像大小,参数二表示通道数。
10. Scalar
m4 = Scalar(255, 255, 0);
解析:给图像设置颜色。因为是给三个通道的图像设置颜色,所以这里使用三个参数;如果是给单通道设置颜色,则设置一个参数即可。
11. cols
int width = m4.cols;
解析:获取图像的宽度。
12. rows
int height = m4.rows;
解析:获取图像的高度。
13. channels
int channels = m4.channels();
解析:获取通向的通道数。单通道表示灰色图像,三通道表示彩色图像。
14. add
add(image, m1, dst1);
解析:图像的像素相加。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相加后输出到参数三。
15. subtract
subtract(image, m2, dst2);
解析:图像的像素相减。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相减后输出到参数三。
16. multiply
multiply(image, m3, dst3);
解析:图像的像素相乘。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相乘后输出到参数三。
17. divide
divide(image, m4, dst4);
解析:图像的像素相除。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相除后输出到参数三。
18. waitKey
int c = waitKey(100);
解析:等待键盘输入,如果参数设置的毫秒数结束后还没有键盘输入,则默认输入-1,结束等待。
19. applyColorMap
applyColorMap(image, dst, COLORMAP_COOL);
解析:设置图像彩色映射。参数一是输入图像,参数二是输出图像,参数三是映射的颜色类型,他是枚举enum ColormapTypes。
20. bitwise_and
bitwise_and(m1, m2, dst1);
解析:图像像素逻辑与操作。参数一和参数二是输入图像,参数三是输出图像。
21. bitwise_or
bitwise_or(m1, m2, dst2);
解析:图像像素逻辑或操作。参数一和参数二是输入图像,参数三是输出图像。
22. bitwise_not
bitwise_not(image, dst3);
解析:图像像素取反操作。参数一是输入图像,参数二是输出图像。
23. bitwise_xor
bitwise_xor(m1, m2, dst4);
解析:图像像素逻辑异或操作。参数一和参数二是输入图像,参数三是输出图像。
24. split
- std::vector
mv; - split(image, mv);
解析:通道分离。
25. rectangle
rectangle(dst1, rect, Scalar(0, 255, 255), 2, 8, 0);
解析:绘制一个矩形。参数一是输出图像,参数二是矩形对象,参数三是颜色,参数四是边框厚度,参数五是反锯齿(可以使用LINE_AA效果更加),参数六不清楚。
如果是需要填充,则将参数四传入-1。
26. circle
circle(dst1, Point(300, 400), 30, Scalar(255, 0, 255), 2, 8, 0);
解析:绘制一个圆形。参数一是输出图像,参数二是圆的中心位置,参数三是圆的半径,参数四是颜色,参数五是边框厚度,参数六是反锯齿(可以使用LINE_AA效果更加),参数七不清楚。
如果是需要填充,则将参数五传入-1。
27. line
line(dst5, Point(100, 130), Point(300, 400), Scalar(255, 0, 0), 2, 8, 0);
解析:绘制一条线。参数一是输入输出图像, 参数二是第一个点位置,参数三是第二个点位置,参数四是颜色,参数五是线的宽度,参数六是反锯齿,参数七不清楚。
28. RNG
- RNG rng((unsigned)time(NULL)); // 用系统时间作为种子初始化rng,要用到time.h库
- int b = rng.uniform(0, 255); // 随机生成 0 - 255
解析:opencv的随机函数。
29. drawContours
drawContours(canvas, contours, 0, Scalar(255, 0, 0), -1);
解析:绘制多边形或者填充多边形。参数一是输入输出图像,参数二是std::vector
30. resize
resize(image, zoomin, Size(w / 2, h / 2));
解析:图像缩放。参数一是输入图像,参数二是输出图像,参数三是重新设置的图像大小。
31. flip
- // 上下翻转
- flip(image, dst, 0);
-
- // 左右翻转
- flip(image, dst, 1);
-
- // 先左右翻转再上下翻转
- flip(image, dst, -1);
解析:图像翻转。参数一是输入图像,参数二是输出图像,参数三0表示上下翻转,1表示左右翻转,-1表示先左右翻转再上下翻转。
以下函数的参数都基于此读取的图像对象:
- int main(void) {
-
- // 正常:IMREAD_COLOR
- // 灰度:IMREAD_GRAYSCALE
- Mat image = imread("图.jpeg", IMREAD_COLOR);
- if (image.empty()) {
- printf("path image NULL!\n");
- return -1;
- }
-
- imshow("原图", image);
-
- waitKey(0);
- destroyAllWindows();
-
- return 0;
- }
- /* 图像色彩空间转换 */
- void colorSpace_Demo(Mat &image) {
- Mat gray, hsv;
-
- cvtColor(image, hsv, COLOR_BGR2HSV);
- cvtColor(image, gray, COLOR_BGR2GRAY); // 灰度图像
-
- imshow("HSV", hsv);
- imshow("灰度", gray);
-
- imwrite("HSV.png", hsv);
- imwrite("GRAY.png", gray);
- }
运行截图

- /* Mat对象的创建与赋值 */
- void mat_creation_demo(Mat &image) {
-
- Mat m1, m2, m3;
-
- // 克隆
- m1 = image.clone(); // 深拷贝
- // 拷贝
- image.copyTo(m2); // 深拷贝
-
- // 赋值
- m3 = image; // 浅拷贝
-
- // 创建空白图像
- //Mat m4 = Mat::zeros(Size(8, 8), CV_8UC1); // 创建一通道
- Mat m4 = Mat::zeros(Size(128, 128), CV_8UC3); // 最后的数字表示通道数
- // 给通道赋值(相当于设置颜色)
- m4 = Scalar(123, 200, 100); // 因为是3通道,所以赋三个值;如果是一通道,给一个参数值即可
- //std::cout << m4 << std::endl;
-
- imshow("m4", m4);
-
- // 图像的宽
- int width = m4.cols;
- // 图像的高
- int height = m4.rows;
- // 图像的通道数
- int channels = m4.channels();
- printf("width = %d\theight = %d\tchannels = %d\n", width, height, channels);
-
-
- // C++11新出的创建空白图像方法
- Mat kernel = (Mat_<char>(3, 3) <<
- 0, -1, 0,
- -1, 5, -1,
- 0, -1, 0);
- kernel = Scalar(50, 100, 150);
- imshow("kernel", kernel);
- }
运行截图

- /* 图像像素的读写操作 */
- void pixel_visit_demo(Mat &image) {
-
- int w = image.cols; // 获取图像宽
- int h = image.rows; // 获取图像高
- int dims = image.channels(); // 获取图像通道数
-
- /* 数组方式 */
- //for (int row = 0; row < h; row++) {
- // for (int col = 0; col < w; col++) {
- // // 单通道 - 灰色图像
- // if (1 == dims) {
- // // 获取通道中的值
- // int pv = image.at
(row, col); - // // 还可以对其进行修改
- // image.at
(row, col) = 255 - pv; // 得确保值在0-255区间 -
- // } else if (3 == dims) { // 三通道 - 彩色图像
- // // 获取通道中的三个值
- // Vec3b bgr = image.at
(row, col); - // // 还可以对其进行修改
- // image.at
(row, col)[0] = 255 - bgr[0]; - // image.at
(row, col)[1] = 255 - bgr[1]; - // image.at
(row, col)[2] = 255 - bgr[2]; - // }
- // }
- //}
-
-
- /* 指针方式 */
- for (int row = 0; row < h; row++) {
- uchar *current_row = image.ptr
(row); -
- for (int col = 0; col < w; col++) {
- if (1 == dims) {
- *current_row++ = 255 - *current_row;
-
- } else if (3 == dims) {
- *current_row++ = 255 - *current_row;
- *current_row++ = 255 - *current_row;
- *current_row++ = 255 - *current_row;
- }
- }
- }
-
- imshow("pixel_visit_demo", image);
- }
运行截图:

- /* 图像像素的算术操作 */
- void operators_demo(Mat &image) {
-
- // 加
- Mat dst1;
- Mat m1 = Mat::zeros(image.size(), image.type());
- m1 = Scalar(100, 100, 100); // 给通道赋值(相当于设置颜色)
- add(image, m1, dst1);
- imshow("图像像素加法操作", dst1);
-
- // 减
- Mat dst2;
- Mat m2 = Mat::zeros(image.size(), image.type());
- m2 = Scalar(50, 50, 50);
- subtract(image, m2, dst2);
- imshow("图像像素减法操作", dst2);
-
- // 乘
- Mat dst3;
- Mat m3 = Mat::zeros(image.size(), image.type());
- m3 = Scalar(2, 2, 2);
- multiply(image, m3, dst3); // 参数一乘以参数二结果给参数三
- imshow("图像像素乘法操作", dst3);
-
- // 除
- Mat dst4;
- Mat m4 = Mat::zeros(image.size(), image.type());
- m4 = Scalar(5, 5, 5);
- divide(image, m4, dst4);
- imshow("图像像素除法操作", dst4);
-
-
- ///* 另外一种方式实现加法操作 */
- //Mat dst5 = Mat::zeros(image.size(), image.type());
- //Mat m5 = Mat::zeros(image.size(), image.type());
- //m5 = Scalar(50, 50, 50);
-
- //int w = image.cols;
- //int h = image.rows;
- //int dims = image.channels();
-
- //for (int row = 0; row < h; row++) {
- // for (int col = 0; col < w; col++) {
- // if (3 == dims) {
- // Vec3b p1 = image.at
(row, col); - // Vec3b p2 = m5.at
(row, col); - // // 加减乘除都是一样的
- // dst5.at
(row, col)[0] = saturate_cast(p1[0] + p2[0]); - // dst5.at
(row, col)[1] = saturate_cast(p1[1] + p2[1]); - // dst5.at
(row, col)[2] = saturate_cast(p1[2] + p2[2]); - // }
- //
- // }
- //}
- //imshow("图像像素加法操作", dst5);
- }
运行截图

- static void on_track(int b, void *userdata) {
-
- Mat image = *((Mat*)userdata);
- Mat dst = Mat::zeros(image.size(), image.type());
- Mat m = Mat::zeros(image.size(), image.type());
- m = Scalar(b, b, b);
- add(image, m, dst);
- imshow("亮度调整", dst);
- }
- /* 滚动条操作演示 */
- void tracking_bar_demo(Mat &image) {
- namedWindow("亮度调整", WINDOW_AUTOSIZE);
- int lightness = 0;
- int max_value = 100;
- // 创建一个滚动条
- createTrackbar("Value Bar:", "亮度调整", &lightness, max_value, on_track, (void*)(&image));
- on_track(lightness, &image);
- }
运行截图

- /* 键盘响应操作 */
- void key_demo(Mat &image) {
- bool flag = true;
-
- Mat input;
- image.copyTo(input);
-
- while (flag) {
- int c = waitKey(100); // 等待键盘输入,等待100ms
- printf("按键:%d\n", c);
-
- switch (c) {
- case 27: { // Esc退出
- flag = false;
- }
- break;
-
- case 52: { // 4 向左旋转
-
- }
- break;
-
- case 54: { // 6 向右旋转
-
- }
- break;
-
- case 56: { // 8 放大
-
- }
- break;
-
- case 50: { // 2 缩小
-
- }
- break;
-
- case 48: { // 0 复原
-
- }
- break;
-
- default:
- break;
- }
-
- imshow("原图", image);
- }
- }
这个键盘响应,我用来写了一个小demo,通过键盘按键来对图片进行旋转、缩放、平移、翻转和裁剪的操作。
- /* OpenCV自带颜色表操作 */
- void color_style_demo(Mat &image) {
-
- int colorMap[] = {
- COLORMAP_AUTUMN,
- COLORMAP_BONE,
- COLORMAP_CIVIDIS,
- COLORMAP_COOL,
- COLORMAP_DEEPGREEN,
- COLORMAP_HOT,
- COLORMAP_HSV,
- COLORMAP_INFERNO,
- COLORMAP_JET,
- COLORMAP_MAGMA,
- COLORMAP_OCEAN,
- COLORMAP_PARULA,
- COLORMAP_PINK,
- COLORMAP_PLASMA,
- COLORMAP_RAINBOW,
- COLORMAP_SPRING,
- COLORMAP_SUMMER,
- COLORMAP_TURBO,
- COLORMAP_TWILIGHT,
- COLORMAP_TWILIGHT_SHIFTED,
- COLORMAP_VIRIDIS,
- COLORMAP_WINTER,
- DECOMP_NORMAL
- };
-
- Mat dst;
- int index = 0;
-
- while (1) {
- int c = waitKey(1000);
- if (27 == c) {
- break;
- }
-
- applyColorMap(image, dst, colorMap[index % 19]);
- index++;
-
- imshow("Opencv自带颜色表", dst);
- }
- }
数组colorMap中存储的,都是enum ColormapTypes枚举中的数据。
运行截图

- /* 图像像素的逻辑操作 */
- void bitwise_demo(Mat &image) {
-
- Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
- Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
- rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);
- rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
- imshow("m1", m1);
- imshow("m2", m2);
-
- // 逻辑与
- Mat dst1;
- bitwise_and(m1, m2, dst1);
- imshow("逻辑与", dst1);
-
- // 逻辑或
- Mat dst2;
- bitwise_or(m1, m2, dst2);
- imshow("逻辑或", dst2);
-
- // 逻辑非
- Mat dst3;
- bitwise_not(image, dst3);
- imshow("逻辑非", dst3);
-
- // 逻辑异或
- Mat dst4;
- bitwise_xor(m1, m2, dst4);
- imshow("逻辑异或", dst4);
- }
运行截图

- /* 通道分离与合并 */
- void channels_demo(Mat &image) {
- std::vector
mv; - // 将一个多通道数组划分为多个单通道数组
- split(image, mv);
- imshow("blue", mv.at(0));
- imshow("green", mv.at(1));
- imshow("red", mv.at(2));
-
-
- Mat dst;
- //mv.at(1) = 0;
- mv.at(2) = 0;
- // 通道合并
- merge(mv, dst);
- imshow("合并通道颜色", dst);
-
-
- int from_to[] = { 0, 2, 1, 1, 2, 0 }; // 将0 和 2通道交换
- // 通道混合
- mixChannels(&image, 1, &dst, 1, from_to, 3);
- imshow("通道混合", dst);
- }
运行截图

- /* 图像色彩空间转换 */
- void inrange_demo(Mat &image) {
- Mat hsv;
- // 转换位hsv的色彩空间
- cvtColor(image, hsv, COLOR_BGR2HSV);
- Mat mask;
- inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask); // 将草莓扣掉
-
- Mat redback = Mat::zeros(image.size(), image.type());
- redback = Scalar(40, 40, 200); // 红色背景图
- bitwise_not(mask, mask); // 逻辑非
- imshow("mask", mask);
- image.copyTo(redback, mask); // 将原图草莓图中按照mask里白色区域拷贝到参数一中
- imshow("roi区域提取", redback);
- }
运行截图

- /* 图像像素值统计 */
- void pixel_statistic_demo(Mat &image) {
- double minv, maxv;
- Point minLoc, maxLoc;
- std::vector
mv; -
- split(image, mv); // 通道分离
-
- for (int i = 0; i < mv.size(); i++) {
- // 找出通道中的最大值和最小值
- minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
- printf("No.channels:%d\tminvalue:%f\tmaxvalue:%f\n", i, minv, maxv);
- }
-
- Mat mean, stddev;
- // 计算矩阵的均值和标准偏差
- meanStdDev(image, mean, stddev);
- std::cout << "means: " << mean << std::endl;
- std::cout << "stddev:" << stddev << std::endl;
- }
运行截图

- /* 图像几何形状绘制 */
- void drawing_demo(Mat &image) {
- Rect rect;
- rect.x = 100;
- rect.y = 130;
- rect.width = 200;
- rect.height = 270;
-
-
- Mat dst1 = image.clone();
- Mat dst2 = image.clone();
-
- // 绘制一个矩形
- rectangle(dst1, rect, Scalar(0, 255, 255), 2, 8, 0);
- // 绘制一个圆形
- circle(dst1, Point(300, 400), 30, Scalar(255, 0, 255), 2, 8, 0);
- imshow("绘制演示", dst1);
-
- // 填充一个矩形
- rectangle(dst2, rect, Scalar(255, 255, 0), -1, 8, 0);
- // 填充一个圆形
- circle(dst2, Point(100, 400), 30, Scalar(0, 255, 0), -1, 8, 0);
- imshow("填充演示", dst2);
-
- Mat dst5 = image.clone();
- // 绘制线
- line(dst5, Point(100, 130), Point(300, 400), Scalar(255, 0, 0), 2, 8, 0);
- // 绘制椭圆
- RotatedRect rrt;
- rrt.center = Point(200, 200);
- rrt.size = Size(100, 200);
- rrt.angle = 90.0;
- ellipse(dst5, rrt, Scalar(0, 0, 255), 2, 8); // 如果需要填充,第四个参数传-1
- imshow("线和椭圆", dst5);
-
-
- Mat dst3, dst4;
- dst3 = Mat::zeros(image.size(), image.type());
- dst3 = Scalar(100, 180, 200);
- imshow("dst3", dst3);
- // 将两张相同大小,相同类型的图片融合的函数
- addWeighted(image, 0.7, dst3, 0.5, 1, dst4);
- imshow("两种图片融合", dst4);
- }
运行截图

- /* 随机数与随机颜色 */
- void random_drawing_demo() {
- Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
- int w = canvas.cols;
- int h = canvas.rows;
- RNG rng((unsigned)time(NULL)); // 用系统时间作为种子初始化rng,要用到time.h库
-
- while (1) {
- int c = waitKey(10);
- if (27 == c) {
- break;
- }
-
- canvas = Scalar(0, 0, 0);
-
- // 获得随机值
- int x1 = rng.uniform(0, w);
- int y1 = rng.uniform(0, h);
- int x2 = rng.uniform(0, w);
- int y2 = rng.uniform(0, h);
- int b = rng.uniform(0, 255);
- int g = rng.uniform(0, 255);
- int r = rng.uniform(0, 255);
- line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA, 0);
-
- imshow("随机数与随机颜色", canvas);
- }
- }
运行截图

- /* 多边形填充与绘制 */
- void polyline_drawing_demo() {
- Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
- Point p1(100, 100);
- Point p2(350, 120);
- Point p3(300, 350);
- Point p4(450, 500);
- Point p5(50, 200);
- std::vector
pts; - pts.emplace_back(p1);
- pts.emplace_back(p2);
- pts.emplace_back(p3);
- pts.emplace_back(p4);
- pts.emplace_back(p5);
- // 填充一个多边形
- //fillPoly(canvas, pts, Scalar(255, 0, 255), 8, 0);
- // 绘制一个多边形
- //polylines(canvas, pts, true, Scalar(0, 0, 255), 2, LINE_AA, 0);
-
- std::vector
> contours; - contours.push_back(pts);
- // 绘制多边形或者填充多边形,参数三指定绘制容器中指定数据的第几个(-1表示全都绘制),最后一个参数为多边形的边框(-1表示填充)
- drawContours(canvas, contours, 0, Scalar(255, 0, 0), -1);
- imshow("多边形填充与绘制", canvas);
- }
运行截图

- Point sp(-1, -1);
- Point ep(-1, -1);
- Mat temp;
- static void on_draw(int event, int x, int y, int flags, void *userdata) {
- Mat image = *((Mat*)userdata);
- if (event == EVENT_LBUTTONDOWN) { // 鼠标左键按下
- sp.x = x; // 获取鼠标坐下按下后的位置坐标
- sp.y = y;
- std::cout << "start point:" << sp << std::endl;
-
- } else if (event == EVENT_LBUTTONUP) {
- ep.x = x; // 获得鼠标松开后的位置坐标
- ep.y = y;
- // 相减得出长和宽
- int dx = ep.x - sp.x;
- int dy = ep.y - sp.y;
- if (dx > 0 && dy > 0 && ep.y < image.size().height && ep.x < image.size().width) {
- Rect box(sp.x, sp.y, dx, dy);
- rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0); // 绘制矩形
- imshow("鼠标绘制", image);
- imshow("ROI区域提取", temp(box)); // 提取矩形中的图像
-
- } else {
- temp.copyTo(image);
- imshow("鼠标绘制", image);
- }
- sp.x = -1;
- sp.y = -1;
-
- } else if (event == EVENT_MOUSEMOVE) {
- if (sp.x > 0 && sp.y > 0) {
- ep.x = x;
- ep.y = y;
- int dx = ep.x - sp.x;
- int dy = ep.y - sp.y;
- if (dx > 0 && dy > 0) {
- temp.copyTo(image);
- Rect box(sp.x, sp.y, dx, dy);
- rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
- imshow("鼠标绘制", image);
- }
- }
- }
- }
- /* 鼠标操作与响应 */
- void mouse_drawing_demo(Mat &image) {
- namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
- // 设置鼠标回调
- setMouseCallback("鼠标绘制", on_draw, (void*)(&image));
- imshow("鼠标绘制", image);
- temp = image.clone();
- }
运行截图

- /* 图像像素类型转换与归一化 */
- void norm_demo(Mat &image) {
- Mat dst;
- std::cout << image.type() << std::endl;
- image.convertTo(image, CV_32F);
- std::cout << image.type() << std::endl;
- normalize(image, dst, 1.0, 0, NORM_MINMAX);
- std::cout << dst.type() << std::endl;
- imshow("图像数据归一化", dst);
- }
运行截图

- /* 图像缩放与插值 */
- void resize_demo(Mat &image) {
- Mat zoomin, zoomout;
- int h = image.rows;
- int w = image.cols;
- resize(image, zoomin, Size(w / 2, h / 2), 0, 0, INTER_LINEAR);
- imshow("zoomin", zoomin);
- resize(image, zoomout, Size(w*1.5, h*1.5), 0, 0, INTER_LINEAR);
- imshow("zoomout", zoomout);
- }
运行截图

- /* 图像翻转 */
- void flip_demo(Mat &image) {
- Mat dst;
-
- // 上下翻转
- flip(image, dst, 0);
-
- // 左右翻转
- //flip(image, dst, 1);
-
- // 先左右翻转再上下翻转
- //flip(image, dst, -1);
-
- imshow("图像翻转", dst);
- }
运行截图

- /* 图像旋转 */
- void rotate_demo(Mat &image) {
- Mat dst, M;
-
- int w = image.cols;
- int h = image.rows;
- M = getRotationMatrix2D(Point2f(w / 2, h / 2), -45, 1.0);
-
- // 计算旋转后需要多大的窗体才能完全装下旋转后的图像
- double cos = abs(M.at<double>(0, 0));
- double sin = abs(M.at<double>(0, 1));
- int nw = cos * w + sin * h;
- int nh = sin * w + cos * h;
- M.at<double>(0, 2) += (nw / 2 - w / 2);
- M.at<double>(1, 2) += (nh / 2 - h / 2);
-
- warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(255, 0, 0));
-
- imshow("图像旋转", dst);
- }
运行截图

- /* 视频文件摄像头使用 */
- void video_demo() {
- // VideoCapture capture(0); // 参数是0,就是读取电脑摄像头
- VideoCapture capture("E:\\Code\\vs2017Code\\OpencvTest2\\OpencvTest2\\win10.mp4");
-
- // 视频宽
- int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
- // 视频高
- int frame_hegiht = capture.get(CAP_PROP_FRAME_HEIGHT);
- // 视频总帧率
- int count = capture.get(CAP_PROP_FRAME_COUNT);
- // 视频每秒多少fps(每秒多少帧)
- double fps = capture.get(CAP_PROP_FPS);
- std::cout << "froma_width:" << frame_width << std::endl;
- std::cout << "frame_hegiht:" << frame_hegiht << std::endl;
- std::cout << "count:" << count << std::endl;
- std::cout << "fps:" << fps << std::endl;
-
- // 定义视频保存对象
- VideoWriter writer("D://test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_hegiht), true);
-
- Mat frame;
- while (1) {
- capture.read(frame); // 读取画面
- //flip(frame, frame, 1); // 左右翻转,读取电脑摄像头时需要翻转,视频不用
- if (frame.empty()) {
- break;
- }
- imshow("frame", frame);
-
- // 保存视频
- writer.write(frame);
-
- int c = waitKey(10);
- if (27 == c) {
- break;
- }
- }
-
- // 释放
- capture.release();
- writer.release();
- }
运行截图

- /* 图像卷积操作 */
- void blur_demo(Mat &image) {
- Mat dst;
- blur(image, dst, Size(1, 1), Point(-1, -1)); // // 设置参数三的数值即可
- imshow("图像模糊", dst);
- }
运行截图

- /* 高斯模糊 */
- void gaussian_blur_demo(Mat &image) {
- Mat dst;
- GaussianBlur(image, dst, Size(0, 0), 5); // 参数三默认0即可,设置参数四实现模糊
- imshow("高斯模糊", dst);
- }
运行截图

- /* 高斯双边模糊 */
- void bifilter_demo(Mat &image) {
- Mat dst;
- bilateralFilter(image, dst, 0, 100, 10);
- imshow("双边模糊", dst);
- }
运行截图

对图片操作,旋转,缩放,平移,翻转,裁剪的操作。
- #include
-
- using namespace cv;
-
-
- void imageOperate1(Mat &image, Mat input, double angle, double scale, int xOffset, int yOffset, int startRow, int &endRow, int startCol, int &endCol, bool up_down, bool left_right) {
-
- input.copyTo(image);
-
-
- // 图像平移
- Size dst_sz = image.size();
- //定义平移矩阵
- Mat t_mat = Mat::zeros(2, 3, CV_32FC1);
- t_mat.at<float>(0, 0) = 1;
- t_mat.at<float>(0, 2) = xOffset; //水平平移量
- t_mat.at<float>(1, 1) = 1;
- t_mat.at<float>(1, 2) = yOffset; //竖直平移量
- //根据平移矩阵进行仿射变换
- warpAffine(image, image, t_mat, dst_sz);
-
- // 旋转图像
- Point2f center((image.cols - 1) / 2.0, (image.rows - 1) / 2.0); // 图像中心位置
- Mat rotation_matix = getRotationMatrix2D(center, angle, 1.0);
- warpAffine(image, image, rotation_matix, image.size());
-
- // 缩放图像
- int width = int(input.cols * scale);
- int height = int(input.rows * scale);
- resize(image, image, cv::Size(width, height), 0, 0, INTER_LINEAR);
-
-
- if (0 == endRow) { // 发生了缩放操作
- endRow = height;
- endCol = width;
- }
- // 裁剪图像
- image = image(Range(startRow, endRow), Range(startCol, endCol));
-
- // 上下翻转
- if (up_down) flip(image, image, 0);
-
- // 左右翻转
- if (left_right) flip(image, image, 1);
- }
- /* 键盘响应操作 */
- void key_demo1(Mat &image) {
- bool flag = true;
- double scale = 1.0; // 缩放比例
- double angle = 0; // 旋转角度
- int xOffset = 0; // 水平平移量
- int yOffset = 0; // 竖直平移量
- int startRow = 0; // 裁剪起始行
- int endRow = image.size().height; // 裁剪结束行
- int startCol = 0; // 裁剪起始列
- int endCol = image.size().width; // 才接结束列
- bool up_down = false; // 上下翻转
- bool left_right = false; // 左右翻转
-
- Mat input;
- image.copyTo(input);
-
- while (flag) {
- int c = waitKey(100); // 等待键盘输入,等待100ms
- printf("按键:%d\n", c);
-
- switch (c) {
- case 27:
- { // Esc退出
- flag = false;
- }
- break;
-
- case 52:
- { // 4 向左旋转
- angle += 5;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 54:
- { // 6 向右旋转
- angle -= 5;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 56:
- { // 8 放大
-
- scale += 0.1;
- if (scale <= 2.05) { // 设置最大放大是2
- endRow = 0;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- scale = 2.0;
- }
-
- }
- break;
-
- case 50:
- { // 2 缩小
-
- scale -= 0.1;
- if (scale >= 0.15) { // 最小缩小是0.2
- endRow = 0;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- scale = 0.2;
- }
-
- }
- break;
-
- case 87:
- case 119:
- { // wW 图片上移
-
- yOffset -= 2;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 83:
- case 115:
- { // sS 图片下移
-
- yOffset += 2;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 65:
- case 97:
- { // aA 图片左移
- xOffset -= 2;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 68:
- case 100:
- { // dD 图片右移
- xOffset += 2;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 73:
- { // I 图片上边复原
- if (startRow > 0) {
- startRow -= 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- startRow = 0;
- }
-
- }
- break;
-
- case 105:
- { // i 图片上边裁剪
-
- if (startRow < endRow - 1) {
- startRow += 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- startRow = endRow - 1;
- }
- }
- break;
-
- case 75:
- { // K 图片下边复原
- if (endRow < input.size().height) {
- endRow += 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- endRow = input.size().height;
- }
- }
- break;
-
- case 107:
- { // k 图片下边裁剪
- if (endRow > startRow + 1) {
- endRow -= 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- endRow = startRow + 1;
- }
- }
- break;
-
- case 74:
- { // J 图片左边恢复
- if (startCol > 0) {
- startCol -= 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- startCol = 0;
- }
- }
- break;
-
- case 106:
- { // j 图片左边裁剪
- if (startCol < endCol - 1) {
- startCol += 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- startCol = endCol - 1;
- }
- }
- break;
-
- case 76:
- { // L 图片右边复原
- if (endCol < input.size().width) {
- endCol += 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- endCol = input.size().width;
- }
- }
- break;
-
- case 108:
- { // l 图片右边裁剪
- if (endCol > startCol + 1) {
- endCol -= 1;
-
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
-
- } else {
- endCol = startCol + 1;
- }
- }
- break;
-
- case 43:
- { // + 上下翻转
- up_down = !up_down;
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 45:
- { // - 左右翻转
- left_right = !left_right;
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- case 48:
- { // 0 复原
- scale = 1.0; // 缩放比例
- angle = 0; // 旋转角度
- xOffset = 0; // 水平平移量
- yOffset = 0; // 竖直平移量
- startRow = 0; // 裁剪起始行
- endRow = input.size().height; // 裁剪结束行
- startCol = 0; // 裁剪起始列
- endCol = input.size().width; // 才接结束列
- up_down = false; // 上下翻转
- left_right = false; // 左右翻转
- imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);
- }
- break;
-
- default:
- break;
- }
-
- imshow("原图", image);
- }
- }
-
-
- int main(void) {
-
- Mat image = imread("图.jpeg", IMREAD_COLOR);
- if (image.empty()) {
- printf("path image NULL!\n");
- return -1;
- }
-
- imshow("原图", image);
-
- key_demo1(image);
-
- waitKey(0);
- destroyAllWindows();
-
- return 0;
- }
运行截图

- #include
- #include
- #include "opencv2/opencv.hpp"
-
- using namespace cv;
-
-
- // 图片旋转
- Mat imageRotate(Mat input, double angle) {
- angle *= -1;
-
- // get the center coordinates of the image to create the 2D rotation matrix
- Point2f center((input.cols - 1) / 2.0, (input.rows - 1) / 2.0);
- // using getRotationMatrix2D() to get the rotation matrix
- Mat rotation_matix = getRotationMatrix2D(center, angle, 1.0);
-
- Mat newImage;
- warpAffine(input, newImage, rotation_matix, input.size());
- //namedWindow("测试图片旋转", WINDOW_FREERATIO);
- //imshow("测试图片旋转", newImage);
- imshow("测试显示图片", newImage);
-
- return newImage;
- }
-
-
- // 图片缩放
- Mat imageZoom(Mat input, float scaleW, float scaleH) {
-
- //float scaleW = 0.5; // 定义新图像的大小,宽度缩小到80%
- //float scaleH = 0.5; //定义新图像的大小,高度缩小到80%
- int width = int(input.cols * scaleW);
- //定义想要扩大或者缩小后的宽度,src.cols为原图像的宽度,乘以80%则得到想要的大小,并强制转换成int型
- int height = int(input.rows * scaleH);
- //定义想要扩大或者缩小后的高度,src.cols为原图像的高度,乘以80%则得到想要的大小,并强制转换成int型
- cv::Mat dst;
- resize(input, dst, cv::Size(width, height));//缩放图像
-
- //namedWindow("测试图片缩放", WINDOW_FREERATIO);
- //imshow("测试图片缩放", dst);
- imshow("测试显示图片", dst);
-
- return dst;
- }
-
-
- // 图片裁剪
- Mat imageCut(Mat input, int startRow, int endRow, int startCol, int endCol) {
-
- Mat cropped_image = input(Range(startRow, endRow), Range(startCol, endCol));
- //namedWindow("测试裁剪图片", WINDOW_FREERATIO);
- //imshow("测试裁剪图片", cropped_image);
- imshow("测试显示图片", cropped_image);
-
- return cropped_image;
- }
-
-
- // 图像平移
- Mat imageTranslation(Mat srcImage, int xOffset, int yOffset)
- {
- Size dst_sz = srcImage.size();
- //定义平移矩阵
- Mat t_mat = Mat::zeros(2, 3, CV_32FC1);
- t_mat.at<float>(0, 0) = 1;
- t_mat.at<float>(0, 2) = xOffset; //水平平移量
- t_mat.at<float>(1, 1) = 1;
- t_mat.at<float>(1, 2) = yOffset; //竖直平移量
- //根据平移矩阵进行仿射变换
- Mat TranslationMat;
- warpAffine(srcImage, TranslationMat, t_mat, dst_sz);
-
- //namedWindow("测试平移图片", WINDOW_FREERATIO);
- //imshow("测试平移图片", TranslationMat);
- imshow("测试显示图片", TranslationMat);
-
- return TranslationMat;
- }
-
-
- int main(void) {
-
- Mat image =imread("123.png");
- //namedWindow("测试显示图片", WINDOW_FREERATIO); // WINDOW_FREERATIO:可以手动调节大小
- //imshow("测试显示图片", image);
- //waitKey(0);
-
-
- double angle = 120;
- Mat imgRotate = imageRotate(image, angle);
-
- waitKey(0);
-
- float scale = 0.5;
- Mat imgZoom = imageZoom(imgRotate, scale, scale);
-
- waitKey(0);
-
- Mat imgCut = imageCut(imgZoom, 50, 80, 200, 300);
-
- waitKey(0);
-
- imageTranslation(imgCut, 10, 20);
-
- waitKey(0);
- destroyAllWindows();
-
- return 0;
- }
记录一个类型转换:
// char* 转 wchar_t*
wchar_t wcha[255] = { 0 };
MultiByteToWideChar(CP_ACP, 0, text, strlen(text), wcha, 255);
putTextCN.h
- #pragma once
- #include
- #include
- #include
-
- using namespace cv;
-
- // 内部调用
- static void GetStringSize(HDC hDC, const char* str, int* w, int* h);
- // 内部调用
- static void putTextZH(Mat dst, const char* str, Point org, Scalar color, int fontSize,
- const char *fn, bool italic, bool underline, bool lfWeight);
-
- // 外部调用,往图片中写入文字
- extern void putTextZh(InputOutputArray img,
- const char *text,
- Point org,
- int fontSize,
- Scalar color,
- const char *font = "Arial",
- bool italic = false,
- bool underline = false,
- bool lfWeight = false);
putTextCN.cpp
- #include "putTextCN.h"
-
- static void GetStringSize(HDC hDC, const char* str, int* w, int* h) {
- SIZE size;
- GetTextExtentPoint32A(hDC, str, strlen(str), &size);
- if (w != 0) *w = size.cx;
- if (h != 0) *h = size.cy;
- }
-
- static void putTextZH(Mat dst, const char* str, Point org, Scalar color, int fontSize, const char* fn, bool italic, bool underline, bool lfWeight) {
- CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3));
-
- int x, y, r, b;
- if (org.x > dst.cols || org.y > dst.rows) return;
- x = org.x < 0 ? -org.x : 0;
- y = org.y < 0 ? -org.y : 0;
-
- LOGFONTA lf;
- lf.lfHeight = -fontSize;
- lf.lfWidth = 0;
- lf.lfEscapement = 0;
- lf.lfOrientation = 0;
- if (true == lfWeight) { // 粗体
- lf.lfWeight = 700;
- } else {
- lf.lfWeight = 400;
- }
- lf.lfItalic = italic; // 斜体
- lf.lfUnderline = underline; // 下划线
- lf.lfStrikeOut = 0;
- lf.lfCharSet = DEFAULT_CHARSET;
- lf.lfOutPrecision = 0;
- lf.lfClipPrecision = 0;
- lf.lfQuality = PROOF_QUALITY;
- lf.lfPitchAndFamily = 0;
- strcpy_s(lf.lfFaceName, fn);
-
- HFONT hf = CreateFontIndirectA(&lf);
- HDC hDC = CreateCompatibleDC(0);
- HFONT hOldFont = (HFONT)SelectObject(hDC, hf);
-
- int strBaseW = 0, strBaseH = 0;
- int singleRow = 0;
- char buf[1 << 12];
- strcpy_s(buf, str);
- char *bufT[1 << 12]; // 这个用于分隔字符串后剩余的字符,可能会超出。
- //处理多行
- {
- int nnh = 0;
- int cw, ch;
-
- const char* ln = strtok_s(buf, "\n", bufT);
- while (ln != 0) {
- GetStringSize(hDC, ln, &cw, &ch);
- strBaseW = max(strBaseW, cw);
- strBaseH = max(strBaseH, ch);
-
- ln = strtok_s(0, "\n", bufT);
- nnh++;
- }
- singleRow = strBaseH;
- strBaseH *= nnh;
- }
-
- if (org.x + strBaseW < 0 || org.y + strBaseH < 0) {
- SelectObject(hDC, hOldFont);
- DeleteObject(hf);
- DeleteObject(hDC);
- return;
- }
-
- r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1;
- b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1;
- org.x = org.x < 0 ? 0 : org.x;
- org.y = org.y < 0 ? 0 : org.y;
-
- BITMAPINFO bmp = { 0 };
- BITMAPINFOHEADER& bih = bmp.bmiHeader;
- int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4));
-
- bih.biSize = sizeof(BITMAPINFOHEADER);
- bih.biWidth = strBaseW;
- bih.biHeight = strBaseH;
- bih.biPlanes = 1;
- bih.biBitCount = 24;
- bih.biCompression = BI_RGB;
- bih.biSizeImage = strBaseH * strDrawLineStep;
- bih.biClrUsed = 0;
- bih.biClrImportant = 0;
-
- void* pDibData = 0;
- HBITMAP hBmp = CreateDIBSection(hDC, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0);
-
- CV_Assert(pDibData != 0);
- HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, hBmp);
-
- //color.val[2], color.val[1], color.val[0]
- SetTextColor(hDC, RGB(255, 255, 255));
- SetBkColor(hDC, 0);
- //SetStretchBltMode(hDC, COLORONCOLOR);
-
- strcpy_s(buf, str);
- const char* ln = strtok_s(buf, "\n", bufT);
- int outTextY = 0;
- while (ln != 0) {
- TextOutA(hDC, 0, outTextY, ln, strlen(ln));
- outTextY += singleRow;
- ln = strtok_s(0, "\n", bufT);
- }
- uchar* dstData = (uchar*)dst.data;
- int dstStep = dst.step / sizeof(dstData[0]);
- unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep;
- unsigned char* pStr = (unsigned char*)pDibData + x * 3;
- for (int tty = y; tty <= b; ++tty) {
- unsigned char* subImg = pImg + (tty - y) * dstStep;
- unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep;
- for (int ttx = x; ttx <= r; ++ttx) {
- for (int n = 0; n < dst.channels(); ++n) {
- double vtxt = subStr[n] / 255.0;
- int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n];
- subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv);
- }
-
- subStr += 3;
- subImg += dst.channels();
- }
- }
-
- SelectObject(hDC, hOldBmp);
- SelectObject(hDC, hOldFont);
- DeleteObject(hf);
- DeleteObject(hBmp);
- DeleteDC(hDC);
- }
-
- extern void putTextZh(InputOutputArray img,
- const char *text,
- Point org,
- int fontSize,
- Scalar color,
- const char *font,
- bool italic,
- bool underline,
- bool lfWeight) {
-
- Mat src = img.getMat();
-
- putTextZH(src, text, org, color, fontSize, font, italic, underline, lfWeight);
- }
main.cpp
- #include "putTextCN.h"
-
- /* 绘制文字 */
- void putText_demo(Mat &image, char *text) {
-
- putTextZh(image, text, Point(150, 50), 20, Scalar(0, 0, 0), "宋体");
-
- imshow("绘制文字", image);
- }
-
- int main(void) {
-
- // 正常:IMREAD_COLOR
- // 灰度:IMREAD_GRAYSCALE
- Mat image = imread("图.jpeg", IMREAD_COLOR);
- if (image.empty()) {
- printf("path image NULL!\n");
- return -1;
- }
-
- imshow("原图", image);
-
- char str[] = "测试OpenCV绘制文字";
- putText_demo(image, str);
-
- waitKey(0);
- destroyAllWindows();
-
- return 0;
- }
运行截图

opencv对图片一些简单的操作,我也就只会这些简单的了,也是在B站看视频学习后记录下来的代码,具体其他高深的的操作就不会了!