当前位置: 首页 > news >正文

实战OpenCV之绘制图形

基础入门

        OpenCV除了用于图像显示之外,还提供了一系列接口和工具,以帮助开发者在图像上绘制各种图形。这里的图形包括:直线、矩形、圆形、椭圆、多边形等。另外,OpenCV还支持在图像上添加文字,对多张图像进行叠加操作。

        下面,我们将逐一介绍OpenCV中与绘制图形相关的API接口。

        1、绘制直线。使用cv::line()函数,其声明如下。

void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0);

        各个参数的含义如下。

        img:输入输出图像的数组。

        pt1:直线的起点坐标。

        pt2:直线的终点坐标。

        color:直线颜色。

        thickness:线宽。

        lineType:线条类型,如8连接线、抗锯齿线等。

        shift:坐标点分量的位移量。

        2、绘制矩形。使用cv::rectangle()函数,其声明如下。

void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0);

        各个参数的含义如下。

        img:输入输出图像的数组。

        pt1:矩形的左上角坐标。

        pt2:矩形的右下角坐标。

        color: 边框颜色。

        thickness:边框厚度,若为负值则填充矩形内部。

        lineType:同上。

        shift:同上。

        3、绘制圆形。使用cv::circle()函数,其声明如下。

void circle(InputOutputArray img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0);

        各个参数的含义如下。

        img:输入输出图像的数组。

        center:圆心坐标。

        radius:圆半径。

        color: 圆边框颜色。

        thickness:边框厚度,若为负值则填充圆内部。

        lineType:同上。

        shift:同上。

        4、绘制椭圆。使用cv::ellipse()函数,其声明如下。

void ellipse(InputOutputArray img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thickness=1, int lineType=8, int shift=0);

        各个参数的含义如下。

        img:输入输出图像数组。

        center:椭圆中心坐标。

        axes:半轴长度,长轴和短轴。

        angle:长轴与水平方向的夹角(以度为单位)。

        startAngle:开始角度。

        endAngle:结束角度。

        color:椭圆颜色。

        thickness:边框厚度,若为负值则填充椭圆内部。

        lineType:同上。

        shift:同上。

        5、绘制多边形。使用cv::polylines()函数,其声明如下。

void polylines(InputOutputArray img, InputArrayOfArrays pts, bool isClosed, const Scalar& color, int thickness=1, int lineType=8, int shift=0);

        各个参数的含义如下。

        img:输入输出图像数组。

        pts:多边形顶点的坐标集。

        isClosed:是否闭合多边形。

        color:边框颜色。

        thickness:边框厚度,若为负值则填充多边形内部。

        lineType:同上。

        shift:同上。

        6、填充多边形。使用cv::fillPoly()函数,其声明如下。

void fillPoly(InputOutputArray img, InputArrayOfArrays pts, const Scalar& color, int lineType=8, int shift=0, int offset=Point());

        各个参数的含义如下。

        img:输入输出图像数组。

        pts:多边形顶点的坐标集。

        color:填充颜色。

        lineType:同上。

        shift:同上。

        offset:坐标的偏移量。

实战解析

        下面的实战代码使用上述基本绘图函数创建了一个包含多种图形的图像,我们可以通过调整参数来改变这些图形的颜色、位置、大小和其他属性。

#include <opencv2/opencv.hpp>
using namespace cv;#include <iostream>
using namespace std;int main()
{// 创建一个512 x 512的白色背景图像Mat image(512, 512, CV_8UC3, Scalar(255, 255, 255));// 绘制绿色的直线line(image, Point(0, 0), Point(511, 511), Scalar(0, 255, 0), 5);// 绘制红色的矩形rectangle(image, Point(384, 0), Point(510, 128), Scalar(0, 0, 255), 3);// 绘制红色的实心圆circle(image, Point(447, 63), 63, Scalar(0, 0, 255), -1);// 绘制蓝色的椭圆ellipse(image, Point(226, 226), Size(100, 50), 0, 0, 180, Scalar(255, 0, 0), 2);// 绘制多边形vector<Point> polygon;polygon.push_back(Point(200, 100));polygon.push_back(Point(250, 100));polygon.push_back(Point(225, 200));polylines(image, polygon, true, Scalar(255, 255, 0));// 显示图像imshow("Draw Shapes Mode 0", image);cv::waitKey(0);destroyAllWindows();return 0;
}

        执行上面的示例代码,运行效果可参考下图。

添加文字

        有时候,我们希望在图像上添加文字或标注,以增强图像的可读性和信息量。此时,可以使用putText函数。

        putText函数的原型如下。

void putText(InputOutputArray img,          // 输入输出图像const String& text,            // 要显示的文本字符串Point org,                     // 文本起始位置(左下角或左上角)int fontFace,                  // 字体样式double fontScale,              // 字体缩放因子const Scalar& color,           // 文本颜色int thickness = 1,             // 文本线条厚度int lineType = LINE_8,         // 线条类型bool bottomLeftOrigin = true   // 是否以左下角为原点
)

        在下面的实战代码中,我们使用putText()函数在图像上添加了蓝色文本"Hello, Hope_Wisdom"。文本的起始位置为(50, 50),字体为cv::FONT_HERSHEY_SIMPLEX,字体大小为1,颜色为蓝色,线条厚度为2。

#include <opencv2/opencv.hpp>
using namespace cv;#include <iostream>
using namespace std;int main()
{// 读取图像,请替换为你自己的图片路径Mat image = imread("OpenCV.png");// 检查图像是否被正确读取if(image.empty()){cout << "Can not open or find the image" << endl;return -1;}// 创建一个名为"Draw Shapes Mode 1"的窗口,WINDOW_NORMAL允许调整窗口大小namedWindow("Draw Shapes Mode 1", WINDOW_NORMAL);// image.cols代表图像的宽度, image.rows代表图像的高度resizeWindow("Draw Shapes Mode 1", image.cols, image.rows);// 添加蓝色的文本putText(image, "Hello, Hope_Wisdom", Point(50, 50), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 0, 0), 2);// 在窗口中显示图像imshow("Draw Shapes Mode 1", image);waitKey(0);destroyAllWindows();return 0;
}

        执行上面的示例代码,运行效果可参考下图。

图像叠加

        在处理多图像时,我们有时候需要在同一窗口中叠加显示多张图像,这可以通过图像融合来实现。addWeighted函数能够根据给定的权重将两个图像的像素值线性组合,同时还可以添加一个亮度补偿项,以控制最终图像的亮度。注意,使用此函数前,需要确保两个输入图像具有相同的尺寸和通道数,否则需要先进行调整。

        addWeighted函数的原型如下。

Mat addWeighted(const cv::Mat& src1,      // 第一个输入数组double alpha,             // 第一个输入数组的权重const cv::Mat& src2,      // 第二个输入数组double beta,              // 第二个输入数组的权重double gamma,             // 加到和上的标量cv::Mat& dst,             // 输出数组int ddepth = -1           // 可选,输出图像深度;如果设置为负数,则与输入图像深度相同
)

        在下面的实战代码中,我们首先读取了两张图像。如果两张图像的尺寸不一致,我们会使用resize函数来进行调整,以满足addWeighted函数的要求。最后,我们将两张图像以50%的透明度进行了叠加,并将融合后的图像显示出来。

#include <opencv2/opencv.hpp>
using namespace cv;#include <iostream>
using namespace std;int main()
{// 读取图像,请替换为你自己的图片路径Mat image1 = imread("OpenCV.png");Mat image2 = imread("C++.png");// 检查图像是否被正确读取if(image1.empty() || image2.empty()){cout << "Can not open or find the image" << endl;return -1;}// 获取两张图片的尺寸Size size1 = image1.size();Size size2 = image2.size();// 确定目标尺寸,这里以较大尺寸为准Size targetSize = size1.area() > size2.area() ? size1 : size2;// 如果尺寸不一致,调整图片大小if (size1 != targetSize){resize(image1, image1, targetSize);}else if (size2 != targetSize){resize(image2, image2, targetSize);}else{NULL;}// 创建一个空的Mat对象来存放结果Mat result;double alpha = 0.5; // 图像1的透明度double beta = 0.5;  // 图像2的透明度double gamma = 0;   // 亮度补偿,默认为0// 使用addWeighted函数叠加图像,两张图以50%透明度叠加addWeighted(image1, alpha, image2, beta, gamma, result);// 创建一个名为Draw Shapes Mode 2"的窗口,WINDOW_NORMAL允许调整窗口大小namedWindow("Draw Shapes Mode 2", WINDOW_NORMAL);// 在窗口中显示图像imshow("Draw Shapes Mode 2", result);waitKey(0);destroyAllWindows();return 0;
}

        执行上面的示例代码,运行效果可参考下图。

相关文章:

  • JVM 在GC 时的根对象都有那些
  • day_49
  • 代码断点调试
  • LLM 直接偏好优化(DPO)的一些研究
  • springboot框架中filter过滤器的urlPatterns的匹配源码
  • Oracle(81)如何生成AWR报告?
  • 链动 2+1 模式小程序 AI 智能名片商城源码培训邀约策略研究
  • Springsecurity 自定义AuthenticationManager
  • RocketMQ Dashboard
  • 【大数据】什么是数据中台?
  • 【HarmonyOS 4.0】基础组件
  • 海山数据库(He3DB)源码详解:He3DB-XLogWrite函数
  • 揭秘CAAC、AOPA、ALPA、ASFC和UTC无人机执照的差别及实用价值
  • MySQL的延迟复制
  • MySQL存储过程详细讲解和常见问题及性能优化
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • django开发-定时任务的使用
  • Effective Java 笔记(一)
  • ES学习笔记(12)--Symbol
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • java 多线程基础, 我觉得还是有必要看看的
  • Java 内存分配及垃圾回收机制初探
  • Javascript Math对象和Date对象常用方法详解
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • 分享一份非常强势的Android面试题
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 聊聊hikari连接池的leakDetectionThreshold
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 前端
  • 前端面试总结(at, md)
  • 前端自动化解决方案
  • 手写双向链表LinkedList的几个常用功能
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 小程序测试方案初探
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • #mysql 8.0 踩坑日记
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (10)STL算法之搜索(二) 二分查找
  • (13)Hive调优——动态分区导致的小文件问题
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)Kafka 安全之使用 SASL 进行身份验证 —— JAAS 配置、SASL 配置
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .net php 通信,flash与asp/php/asp.net通信的方法