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

OpenCV C++ 学习笔记(六):绘制文本、几何绘图、查找/绘制轮廓

文章目录

  • 绘制文字putText()
  • 绘制直线line()
  • 绘制矩形rectangle()
  • 绘制圆circle()
  • 绘制椭圆或部分弧线ellipse()
  • 绘制多边形/折线polylines()
  • 填充多边形fillPoly()
  • 查找轮廓findContours()
  • 绘制轮廓drawContours()


绘制文字putText()

void cv::putText(Mat& img,              // 目标图像const string& text,    // 待绘制的文本字符串Point org,             // 文本字符串左下角所在位置int fontFace,          // 字体类型double fontScale,      // 字体缩放系数(相对于默认大小)Scalar color,          // 文本颜色 (B,G,R)int thickness = 1,     // 线条宽度int lineType = LINE_8, // 线型bool bottomLeftOrigin = false // 当值为 true 时,原点位于左下角,否则在左上角
);/** @brief Draws a text string.The function cv::putText renders the specified text string in the image. Symbols that cannot be rendered
using the specified font are replaced by question marks. See #getTextSize for a text rendering code
example.@param img Image.
@param text Text string to be drawn.
@param org Bottom-left corner of the text string in the image.
@param fontFace Font type, see #HersheyFonts.
@param fontScale Font scale factor that is multiplied by the font-specific base size.
@param color Text color.
@param thickness Thickness of the lines used to draw a text.
@param lineType Line type. See #LineTypes
@param bottomLeftOrigin When true, the image data origin is at the bottom-left corner. Otherwise,
it is at the top-left corner.*/
  • img: 输入/输出图像,即要在其上绘制文字的图像。
  • text: 要绘制的文本字符串。
  • org: 指定文本起始点的坐标。这个点是文本字符串中第一个字符的左下角(如果 bottomLeftOrigin=false)或者左上角(如果 bottomLeftOrigin=true)的位置。
  • fontFace: 字体类型,支持以下几种:
    • FONT_HERSHEY_SIMPLEX, FONT_HERSHEY_PLAIN
    • FONT_HERSHEY_DUPLEX, FONT_HERSHEY_COMPLEX
    • FONT_HERSHEY_TRIPLEX, FONT_HERSHEY_COMPLEX_SMALL
    • FONT_HERSHEY_SCRIPT_SIMPLEX, FONT_HERSHEY_SCRIPT_COMPLEX
  • fontScale: 字体的比例因子。可以根据需要放大或缩小字体大小。
  • color: 字体颜色,使用 Scalar 对象表示,格式为 (B, G, R)。
  • thickness: 字体线条的厚度。默认值为 1。
  • lineType: 线条类型。通常使用 LINE_8LINE_AA(抗锯齿)。LINE_4 和 LINE_AA 也是可选项。
  • bottomLeftOrigin: 如果此参数设置为 true,则文本的原点将位于左下角;否则,默认情况下,它位于左上角。
cv::Mat image = cv::Mat::zeros(cv::Size(300, 300), CV_8UC3);// 定义文本和字体属性
std::string text = "Hello, OpenCV!";
cv::Point position(50, 150); // 文字起始位置
int fontFace = cv::FONT_HERSHEY_SIMPLEX;
double fontScale = 1.0; // 字体大小
int thickness = 2; // 字体线条厚度// 在图像上绘制文本
cv::putText(image, text, position, fontFace, fontScale, cv::Scalar(255, 0, 0), thickness);// 显示结果图像
cv::imshow("Image with Text", image);

绘制直线line()

void cv::line(Mat& img,              // 目标图像Point pt1,             // 直线起点Point pt2,             // 直线终点const Scalar& color,   // 线条颜色 (B,G,R)int thickness = 1,     // 线条宽度,默认为1int lineType = LINE_8, // 线型,默认为8连通int shift = 0          // 坐标点的小数位数,默认为0
);
  • lineType: 线条类型,可以选择以下几种之一:
    • LINE_4: 4连通线段。
    • LINE_8: 8连通线段(默认)。
    • LINE_AA: 抗锯齿线段,提供更平滑的效果。
cv::Mat image = cv::Mat::zeros(cv::Size(300, 300), CV_8UC3);// 定义直线的起点和终点
cv::Point startPoint(50, 50);
cv::Point endPoint(250, 250);// 定义线条的颜色和粗细
cv::Scalar lineColor(0, 255, 0); // 绿色
int thickness = 2;               // 粗细为2个像素
int lineType = cv::LINE_AA;      // 使用抗锯齿线条// 在图像上绘制直线
cv::line(image, startPoint, endPoint, lineColor, thickness, lineType);

绘制矩形rectangle()

void cv::rectangle(Mat& img,                      // 输入/输出图像Point pt1,                     // 矩形左上角坐标Point pt2,                     // 矩形右下角坐标const Scalar& color,           // 颜色 (B, G, R)int thickness = 1,             // 线条粗细,默认为1int lineType = LINE_8,         // 线型,默认为LINE_8int shift = 0                  // 坐标精度位数,默认为0
);void cv::rectangle(Mat& img,Rect rec,                      // 使用 Rect 定义矩形区域const Scalar& color,int thickness = 1,int lineType = LINE_8,int shift = 0
);
cv::Mat image = cv::Mat::zeros(cv::Size(300, 300), CV_8UC3); // 黑色背景图cv::Point topLeft(50, 50);
cv::Point bottomRight(250, 250);cv::rectangle(image, topLeft, bottomRight, cv::Scalar(0, 255, 0), 2, cv::LINE_AA);// 或
cv::rectangle(image, cv::Rect(50, 50, 200, 200), cv::Scalar(255, 0, 0), 2);// 绘制实心矩形(填充)
cv::rectangle(image, cv::Rect(50, 50, 100, 100), cv::Scalar(0, 0, 255), cv::FILLED);

使用 thickness=cv::FILLED-1 实现实心效果。

绘制圆circle()

void cv::circle(Mat& img,                     // 输入/输出图像阵列,可以是8位或32位浮点型。Point center,                 // 圆心坐标 (x, y)。int radius,                   // 圆的半径。const Scalar& color,          // 圆的颜色。在BGR格式下表示为Scalar(blue, green, red)。int thickness = 1,            // 组成圆的线条的粗细程度。如果为负值,例如 FILLED,则会填充圆形内部。int lineType = LINE_8,        // 圆边界的类型。默认是8连接线。int shift = 0                 // 圆心坐标和半径值的小数位数。
);

thickness 正值表示绘制空心圆,而负值(如 FILLED)则表示绘制实心圆。

cv::Mat image = cv::Mat::zeros(cv::Size(600, 400), CV_8UC3);// 定义圆心位置和半径
cv::Point center = cv::Point(300, 200); // 圆心位于图像中央
int radius = 100; // 半径为100像素// 绘制红色的实心圆
cv::circle(image, center, radius, cv::Scalar(0, 0, 255), -1, cv::LINE_AA);

绘制椭圆或部分弧线ellipse()

void cv::ellipse(Mat& img,                         // 输入/输出图像阵列,可以是8位或32位浮点型。Point center,                     // 椭圆中心的位置 (x, y)。Size axes,                        // 椭圆主轴和次轴的长度。double angle,                     // 椭圆相对于x轴旋转的角度(以度为单位)。double startAngle,                // 椭圆弧起始角度(以度为单位)。double endAngle,                  // 椭圆弧结束角度(以度为单位)。const Scalar& color,              // 椭圆的颜色。在BGR格式下表示为Scalar(blue, green, red)。int thickness = 1,                // 组成椭圆的线条的粗细程度。如果为负值,例如 FILLED,则会填充椭圆内部。int lineType = LINE_8,            // 椭圆边界的类型。默认是8连接线。int shift = 0                     // 中心坐标和轴数值的小数位数。
);
cv::Mat image = cv::Mat::zeros(cv::Size(600, 400), CV_8UC3);// 定义椭圆中心位置、轴长和旋转角度
cv::Point center(300, 200); // 椭圆中心位于图像中央
cv::Size axes(100, 50);     // 椭圆的主轴和次轴长度
double angle = 30;          // 相对x轴顺时针旋转30度
double startAngle = 0;      // 椭圆弧起始角度
double endAngle = 360;      // 椭圆弧结束角度// 绘制蓝色的空心椭圆
cv::ellipse(image, center, axes, angle, startAngle, endAngle, cv::Scalar(255, 0, 0), 2, cv::LINE_AA);

绘制多边形/折线polylines()

void cv::polylines(Mat& img,                         // 输入/输出图像阵列,可以是8位或32位浮点型。const Point* pts,                 // 指向要绘制的多边形顶点数组的指针。const vector<Point>& pts,         // 或者使用Point类型的vector容器代替。bool isClosed,                    // 标志表示所绘制的折线是否闭合。如果为true,则连接最后一个点与第一个点。const Scalar& color,              // 多边形的颜色。在BGR格式下表示为Scalar(blue, green, red)。int thickness = 1,                // 组成多边形的线条的粗细程度。默认值为1。int lineType = LINE_8,            // 线段端点的类型。可选值有LINE_4, LINE_8 (default), LINE_AA(抗锯齿)。int shift = 0                     // 顶点坐标的小数位数。默认值为0。
);// 更常用的重载版本接受一个 vector<vector<Point>> 类型的参数,以便一次绘制多个轮廓void cv::polylines(Mat& img,                                 // 输入/输出图像阵列,可以是8位或32位浮点型。const vector<vector<Point>>& pts,        // 包含每个多边形或折线顶点集合的vector容器。bool isClosed,                           // 标志表示所绘制的折线是否闭合。如果为true,则每个轮廓的最后一个点与第一个点相连。const Scalar& color,                     // 多边形的颜色。在BGR格式下表示为Scalar(blue, green, red)。int thickness = 1,                       // 组成多边形的线条的粗细程度。默认值为1。int lineType = LINE_8,                   // 线段端点的类型。可选值有LINE_4, LINE_8 (default), LINE_AA(抗锯齿)。int shift = 0                            // 顶点坐标的小数位数。默认值为0。
);
cv::Mat image = cv::Mat::zeros(cv::Size(600, 400), CV_8UC3);// 定义多边形顶点
std::vector<std::vector<cv::Point>> contours;
contours.push_back({{100, 100}, {150, 50}, {200, 100}}); // 三角形
contours.push_back({{300, 200}, {350, 150}, {400, 200}, {350, 250}}); // 四边形// 绘制蓝色的闭合多边形
cv::polylines(image, contours, true, cv::Scalar(255, 0, 0), 2, cv::LINE_AA);

填充多边形fillPoly()

void cv::fillPoly(Mat& img,                                // 输入/输出图像阵列,可以是8位或32位浮点型。const Point** pts,                       // 指向要填充的多边形顶点数组的指针。const vector<Point>& pts,                // 或者使用Point类型的vector容器代替。const vector<vector<Point>>& pts,        // 包含每个多边形顶点集合的vector容器。const int npts[],                        // 每个多边形顶点数的数组。int contours,                            // 要绘制的多边形数量。const Scalar& color,                     // 多边形的颜色。在BGR格式下表示为Scalar(blue, green, red)。int lineType = LINE_8,                   // 线段端点的类型。可选值有LINE_4, LINE_8 (default), LINE_AA(抗锯齿)。int shift = 0                            // 顶点坐标的小数位数。默认值为0。
);void cv::fillPoly(Mat& img,                                // 输入/输出图像阵列,可以是8位或32位浮点型。const vector<vector<Point>>& pts,        // 包含每个多边形或折线顶点集合的vector容器。const Scalar& color,                     // 多边形的颜色。在BGR格式下表示为Scalar(blue, green, red)。int lineType = LINE_8,                   // 线段端点的类型。可选值有LINE_4, LINE_8 (default), LINE_AA(抗锯齿)。int shift = 0,                           // 顶点坐标的小数位数。默认值为0。Point offset = Point()                   // 可选的偏移量,应用于所有顶点。
);
cv::Mat image = cv::Mat::zeros(cv::Size(600, 400), CV_8UC3);// 定义多边形顶点
std::vector<std::vector<cv::Point>> contours;
contours.push_back({{100, 100}, {150, 50}, {200, 100}}); // 三角形
contours.push_back({{300, 200}, {350, 150}, {400, 200}, {350, 250}}); // 四边形// 填充红色的三角形和蓝色的四边形
cv::fillPoly(image, contours, cv::Scalar(0, 0, 255), cv::LINE_8, 0, cv::Point());
cv::fillPoly(image, contours, cv::Scalar(255, 0, 0), cv::LINE_8, 0, cv::Point(200, 100)); // 注意第二个图形需要调整偏移以避免覆盖第一个图形

查找轮廓findContours()

用于在二值图像中查找轮廓。轮廓可以简单地理解为连接具有相同颜色或强度的所有连续点(沿着边界)的曲线。它常被用于形状分析、对象检测和识别等领域。

void cv::findContours(InputOutputArray image, // 输入/输出图像,必须是二值图像,非零像素被视为1,0像素保持不变。OutputArrayOfArrays contours, // 检测到的轮廓,每个轮廓存储为一个点向量。OutputArray hierarchy, // 可选输出变量,包含图像拓扑信息的向量。int mode, // 轮廓检索模式。int method, // 轮廓近似方法。Point offset = Point() // 可选偏移量,指定每个轮廓点的可选增量。
);
  • image: 输入的单通道、8位二值图像。在函数执行过程中,这个图像可能会被修改。为了保留原图,建议传入图像的副本。
  • contours: 输出参数,存储所有找到的轮廓。每个轮廓是一个点(x,y坐标)的列表,这些点定义了轮廓的形状。
  • hierarchy: 输出参数,每个轮廓对应的层次结构信息。每个轮廓都有一个与之关联的信息:下一个轮廓、前一个轮廓、第一个子轮廓和父轮廓的索引。
  • mode: 轮廓检索模式,决定了函数如何检索轮廓:
    • RETR_EXTERNAL: 只检索最外层的轮廓。
    • RETR_LIST: 检索所有轮廓并将它们组成一个没有层次结构的列表。
    • RETR_CCOMP: 检索所有轮廓并将它们组织成两级结构:顶层为连通域,第二层为孔洞。
    • RETR_TREE: 检索所有轮廓并重建嵌套轮廓的完整层级结构。
  • method: 轮廓近似方法,指定了如何近似轮廓:
    • CHAIN_APPROX_NONE: 将轮廓中的所有点都存储下来,不进行压缩。
    • CHAIN_APPROX_SIMPLE: 压缩水平、垂直和对角线方向上的点,仅保留它们的端点。
    • CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS: 使用Teh-Chin链逼近算法的一种。
  • offset: 可选参数,指定轮廓点的增量。对于ROI处理非常有用。

绘制轮廓drawContours()

void cv::drawContours(Mat& image,                        // 输入/输出图像const vector<vector<Point>>& contours,  // 轮廓列表(由 findContours 提取)int contourIdx,                    // 要绘制的轮廓索引(-1 表示全部绘制)const Scalar& color,              // 轮廓颜色 (B, G, R)int thickness = 1,                // 线宽或填充标志int lineType = LINE_8,            // 线型:LINE_4 / LINE_8 / LINE_AAconst vector<Vec4i>& hierarchy = vector<Vec4i>(), // 可选的层级结构int maxLevel = INT_MAX,           // 绘制的最大层级(配合 hierarchy 使用)Point offset = Point()            // 可选偏移量,平移所有轮廓点
);
  • image 输入/输出图像,轮廓会直接绘制在该图像上
  • contours 轮廓列表,是一个 vector<vector<cv::Point>> 类型
  • contourIdx 指定要绘制的第几个轮廓,从0开始计数;设为 -1 表示绘制所有轮廓
  • color 轮廓的颜色,使用 Scalar(B, G, R) 格式指定
  • thickness 线条粗细。若为负值(如 cv::FILLED),则填充轮廓内部
  • lineType 线型类型,推荐使用 LINE_AA(抗锯齿)
  • hierarchy 层级结构,与 findContours 返回的层级结构一致
  • maxLevel 最大绘制层级,用于控制嵌套轮廓的绘制深度
  • offset 偏移量,可对所有轮廓点进行整体位移
#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {Mat src = imread("path_to_image", IMREAD_COLOR);if (src.empty()) {cout << "Could not open or find the image" << endl;return -1;}Mat gray, binary;cvtColor(src, gray, COLOR_BGR2GRAY);threshold(gray, binary, 128, 255, THRESH_BINARY);vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);// 绘制轮廓Mat drawing = Mat::zeros(binary.size(), CV_8UC3);for (size_t i = 0; i < contours.size(); i++) {Scalar color = Scalar(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));drawContours(drawing, contours, (int)i, color, 2, LINE_8, hierarchy, 0);}imshow("Contours", drawing);waitKey(0);return 0;
}

首先读取一张图片,并将其转换为灰度图,然后通过阈值处理得到二值图像。接着使用 findContours 在二值图像中查找轮廓,并将这些轮廓drawContours()绘制在一个新的图像上。

// 只绘制第一个轮廓
cv::drawContours(src, contours, 0, cv::Scalar(255, 0, 0), 2); // 蓝色轮廓
// 填充所有轮廓
cv::drawContours(src, contours, -1, cv::Scalar(0, 255, 0), cv::FILLED);
// 只绘制最外层轮廓(层级为0)
cv::drawContours(src, contours, -1, cv::Scalar(255, 0, 0), 2, cv::LINE_AA, hierarchy, 0);
  • 如果只想显示某个对象的轮廓,可以结合掩膜(mask)操作。
  • 若想绘制带透明度的轮廓,可以使用 addWeighted() 实现半透明效果。
http://www.xdnf.cn/news/864523.html

相关文章:

  • [蓝桥杯]取球博弈
  • 【发布实录】云原生+AI,助力企业全球化业务创新
  • Odoo17 技巧 | 如何获取Selection字段的显示值五种方法
  • Cisco IOS XE WLC 任意文件上传漏洞复现(CVE-2025-20188)
  • powershell 安装 .netframework3.5
  • CentOS7 + JDK8 虚拟机安装与 Hadoop + Spark 集群搭建实践
  • .Net Framework 4/C# 集合和索引器
  • C++ 使用 ffmpeg 解码本地视频并获取每帧的YUV数据
  • .NET 9中的异常处理性能提升分析:为什么过去慢,未来快
  • .net jwt实现
  • 12.RSA
  • 使用 React Native 开发鸿蒙运动健康类应用的​​高频易错点总结​​
  • 基于BP神经网络的语音特征信号分类
  • THUNDER:用“听回去”的方式让数字人说话更像真人
  • 内网穿透之Linux版客户端安装(神卓互联)
  • 【学习笔记】TCP 与 UDP
  • 化学方程式配平免费API接口教程
  • 图像处理、图像分析和图像理解的定义、联系与区别
  • vue 多端适配之pxtorem
  • 论文阅读笔记——Large Language Models Are Zero-Shot Fuzzers
  • 如何安全高效的文件管理?文件管理方法
  • MySQL补充知识点学习
  • 【触想智能】工业一体机在工厂智能化升级改造中的作用和应用分析
  • AI数字人在说话时怎样模拟呼吸?
  • Appium+python自动化(九)- 定位元素工具
  • cocos3.X的oops框架oops-plugin-excel-to-json改进兼容多表单导出功能
  • [特殊字符] 在 React Native 项目中封装 App Icon 一键设置命令(支持参数与默认路径)
  • git stash命令用法
  • Docker 部署 Python 的 Flask项目
  • STM32----IAP远程升级