文章目录
- 绘制文字putText()
- 绘制直线line()
- 绘制矩形rectangle()
- 绘制圆circle()
- 绘制椭圆或部分弧线ellipse()
- 绘制多边形/折线polylines()
- 填充多边形fillPoly()
- 查找轮廓findContours()
- 绘制轮廓drawContours()
绘制文字putText()
cpp
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_8
或LINE_AA
(抗锯齿)。LINE_4 和 LINE_AA 也是可选项。bottomLeftOrigin
: 如果此参数设置为 true,则文本的原点将位于左下角;否则,默认情况下,它位于左上角。
cpp
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()
cpp
void cv::line(
Mat& img, // 目标图像
Point pt1, // 直线起点
Point pt2, // 直线终点
const Scalar& color, // 线条颜色 (B,G,R)
int thickness = 1, // 线条宽度,默认为1
int lineType = LINE_8, // 线型,默认为8连通
int shift = 0 // 坐标点的小数位数,默认为0
);
lineType
: 线条类型,可以选择以下几种之一:LINE_4
: 4连通线段。LINE_8
: 8连通线段(默认)。LINE_AA
: 抗锯齿线段,提供更平滑的效果。
cpp
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()
cpp
void cv::rectangle(
Mat& img, // 输入/输出图像
Point pt1, // 矩形左上角坐标
Point pt2, // 矩形右下角坐标
const Scalar& color, // 颜色 (B, G, R)
int thickness = 1, // 线条粗细,默认为1
int lineType = LINE_8, // 线型,默认为LINE_8
int shift = 0 // 坐标精度位数,默认为0
);
void cv::rectangle(
Mat& img,
Rect rec, // 使用 Rect 定义矩形区域
const Scalar& color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0
);
cpp
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()
cpp
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)则表示绘制实心圆。
cpp
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()
cpp
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 // 中心坐标和轴数值的小数位数。
);
cpp
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()
cpp
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。
);
cpp
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()
cpp
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() // 可选的偏移量,应用于所有顶点。
);
cpp
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()
用于在二值图像中查找轮廓。轮廓可以简单地理解为连接具有相同颜色或强度的所有连续点(沿着边界)的曲线。它常被用于形状分析、对象检测和识别等领域。
cpp
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()
cpp
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_AA
const 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
偏移量,可对所有轮廓点进行整体位移
cpp
#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()
绘制在一个新的图像上。
cpp
// 只绘制第一个轮廓
cv::drawContours(src, contours, 0, cv::Scalar(255, 0, 0), 2); // 蓝色轮廓
cpp
// 填充所有轮廓
cv::drawContours(src, contours, -1, cv::Scalar(0, 255, 0), cv::FILLED);
cpp
// 只绘制最外层轮廓(层级为0)
cv::drawContours(src, contours, -1, cv::Scalar(255, 0, 0), 2, cv::LINE_AA, hierarchy, 0);
- 如果只想显示某个对象的轮廓,可以结合掩膜(mask)操作。
- 若想绘制带透明度的轮廓,可以使用
addWeighted()
实现半透明效果。