十一、OpenCV中图形的绘制

文章目录

一、绘制文本

OpenCV 绘制文本主要使用函数 cv::putText()。

cpp 复制代码
void cv::putText(
    cv::Mat& img,                 // 输入图像
    const std::string& text,      // 要绘制的文字
    cv::Point org,                // 起始位置(左下角)
    int fontFace,                 // 字体类型
    double fontScale,             // 字体缩放比例(越大字越大)
    cv::Scalar color,             // 颜色(B,G,R)
    int thickness = 1,            // 线宽
    int lineType = LINE_8,        // 线型,常用 LINE_AA 抗锯齿
    bool bottomLeftOrigin = false // true时y轴反向
);

常用字体类型(fontFace):

  • FONT_HERSHEY_SIMPLEX:普通无衬线字体(最常用)
  • FONT_HERSHEY_PLAIN:小号字体
  • FONT_HERSHEY_DUPLEX:普通字体(比 SIMPLEX 稍粗)
  • FONT_HERSHEY_COMPLEX:复杂字体
  • FONT_HERSHEY_TRIPLEX:更复杂的字体
  • FONT_HERSHEY_COMPLEX_SMALL:小号复杂字体
  • FONT_HERSHEY_SCRIPT_SIMPLEX:手写体
  • FONT_HERSHEY_SCRIPT_COMPLEX:复杂手写体

示例代码:

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    // 创建黑色背景图像
    Mat img = Mat::zeros(Size(800, 400), CV_8UC3);

    // 在图像上绘制不同字体文字
    putText(img, "FONT_HERSHEY_SIMPLEX", Point(50, 50),
            FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255, 255, 255), 2, LINE_AA);

    putText(img, "FONT_HERSHEY_COMPLEX", Point(50, 100),
            FONT_HERSHEY_COMPLEX, 1.0, Scalar(0, 255, 0), 2, LINE_AA);

    putText(img, "FONT_HERSHEY_SCRIPT_SIMPLEX", Point(50, 150),
            FONT_HERSHEY_SCRIPT_SIMPLEX, 1.2, Scalar(0, 255, 255), 2, LINE_AA);

    // 绘制红色数字
    putText(img, "12345", Point(50, 220),
            FONT_HERSHEY_DUPLEX, 2.0, Scalar(0, 0, 255), 3, LINE_AA);

    // 显示结果
    imshow("OpenCV Text Demo", img);
    waitKey(0);
    return 0;
}

OpenCV 自带的 putText() 不支持中文,因为它的字体库只支持 ASCII。

要绘制中文文字,可以使用以下方式之一:

  1. Qt 或 Windows GDI 绘制文字(结合 QImage / HDC);
  2. 使用 cv::freetype 模块(需要额外安装 FreeType 支持);
  3. 将中文先转为图像(例如用 QPainter 或 Pillow),再贴回 OpenCV 图像。

例如使用 FreeType 支持中文:

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/freetype.hpp>
using namespace cv;

int main() {
    Mat img = Mat::zeros(Size(800, 400), CV_8UC3);

    // 创建 FreeType 字体渲染器(需要 freetype 模块)
    Ptr<freetype::FreeType2> ft2 = freetype::createFreeType2();
    ft2->loadFontData("C:/Windows/Fonts/simhei.ttf", 0);  // 黑体字体路径

    ft2->putText(img, "你好,OpenCV!", Point(50, 200),
                 60, Scalar(0, 255, 255), FILLED, LINE_AA, false);

    imshow("Chinese Text Demo", img);
    waitKey(0);
    return 0;
}

二、绘制直线

在 OpenCV 中绘制直线一般使用 cv::line 函数;它的函数原型如下。

函数原型:

cpp 复制代码
void cv::line(
    cv::InputOutputArray img,     // 要绘制的图像
    cv::Point pt1,                // 直线起点
    cv::Point pt2,                // 直线终点
    const cv::Scalar& color,      // 直线颜色 (B, G, R)
    int thickness = 1,            // 线宽,默认1
    int lineType = cv::LINE_8,    // 线型,8连通/4连通/抗锯齿
    int shift = 0                 // 小数点位数,用于亚像素坐标
);

示例代码:

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    // 创建一张黑色背景图像
    Mat image = Mat::zeros(400, 400, CV_8UC3);

    // 起点和终点
    Point pt1(50, 50);
    Point pt2(350, 350);

    // 绘制一条红色直线
    line(image, pt1, pt2, Scalar(0, 0, 255), 2, LINE_AA);

    // 显示图像
    imshow("Line Example", image);
    waitKey(0);
    return 0;
}

输出结果:

三、绘制矩形

在 OpenCV 里绘制矩形使用 cv::rectangle 函数;函数原型如下。

函数原型:

cpp 复制代码
void cv::rectangle(
    cv::InputOutputArray img,     // 要绘制的图像
    cv::Point pt1,                // 矩形左上角点
    cv::Point pt2,                // 矩形右下角点
    const cv::Scalar& color,      // 颜色 (B, G, R)
    int thickness = 1,            // 线宽,-1 表示填充
    int lineType = cv::LINE_8,    // 线型
    int shift = 0                 // 小数点位数(亚像素坐标用)
);

示例代码:

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    // 创建一张黑色背景图像
    Mat image = Mat::zeros(400, 400, CV_8UC3);

    // 定义矩形的两个对角点
    Point pt1(50, 50);   // 左上角
    Point pt2(300, 300); // 右下角

    // 绘制绿色矩形边框
    rectangle(image, pt1, pt2, Scalar(0, 255, 0), 2, LINE_AA);

    // 绘制一个填充的蓝色矩形
    rectangle(image, Point(100, 100), Point(200, 200), Scalar(255, 0, 0), -1);

    // 显示图像
    imshow("Rectangle Example", image);
    waitKey(0);
    return 0;
}

输出结果如下:

四、绘制圆形

在 OpenCV 中绘制圆形可以使用 cv::circle 函数;下面是你详细说明用法和示例,

函数原型:

cpp 复制代码
void cv::circle(
    cv::InputOutputArray img,  // 要绘制的图像
    cv::Point center,          // 圆心坐标
    int radius,                // 半径
    const cv::Scalar& color,   // 颜色 (B,G,R)
    int thickness = 1,         // 线宽,-1 表示填充
    int lineType = cv::LINE_8, // 线型(8连通/4连通/抗锯齿)
    int shift = 0              // 坐标小数点位数
);

示例代码:

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    // 创建黑色背景图
    Mat image = Mat::zeros(400, 400, CV_8UC3);

    // 绘制边框圆(红色,线宽2)
    circle(image, Point(200, 200), 100, Scalar(0, 0, 255), 2, LINE_AA);

    // 绘制填充圆(蓝色)
    circle(image, Point(200, 200), 50, Scalar(255, 0, 0), -1, LINE_AA);

    imshow("Circle Example", image);
    waitKey(0);
    return 0;
}

输出结果如下:

五、绘制椭圆形

在 OpenCV 中绘制椭圆形可以使用 cv::ellipse 函数;下面是详细说明用法和示例。

函数原型:

cpp 复制代码
void cv::ellipse(
    cv::InputOutputArray img,     // 要绘制的图像
    cv::Point center,             // 椭圆中心
    cv::Size axes,                // 椭圆长轴和短轴的一半 (width/2, height/2)
    double angle,                 // 椭圆旋转角度(逆时针,以 x 轴为基准)
    double startAngle,            // 椭圆弧起始角度
    double endAngle,              // 椭圆弧结束角度
    const cv::Scalar& color,      // 颜色 (B, G, R)
    int thickness = 1,            // 线宽,-1 表示填充
    int lineType = cv::LINE_8,    // 线型(8连通/4连通/抗锯齿)
    int shift = 0                 // 坐标小数点位数
);

示例代码:

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    // 创建黑色背景图
    Mat image = Mat::zeros(400, 400, CV_8UC3);

    // 绘制边框椭圆(绿色,线宽2)
    ellipse(image, Point(200, 200), Size(100, 50), 30, 0, 360, Scalar(0, 255, 0), 2, LINE_AA);

    // 绘制填充椭圆(红色)
    ellipse(image, Point(200, 200), Size(50, 100), 0, 0, 360, Scalar(0, 0, 255), -1, LINE_AA);

    imshow("Ellipse Example", image);
    waitKey(0);
    return 0;
}

输出结果如下所示:

六、绘制多边形

绘制多边形边框:cv::polylines

cpp 复制代码
void cv::polylines(
    cv::InputOutputArray img,             // 要绘制的图像
    const std::vector<std::vector<cv::Point>>& pts, // 多边形点集合
    bool isClosed,                        // 是否闭合
    const cv::Scalar& color,              // 颜色 (B, G, R)
    int thickness = 1,                     // 线宽
    int lineType = cv::LINE_8,            // 线型
    int shift = 0                          // 坐标小数点位数
);

示例:绘制闭合三角形

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat image = Mat::zeros(400, 400, CV_8UC3);

    std::vector<Point> triangle = { Point(50, 300), Point(200, 50), Point(350, 300) };
    
    // 注意 polylines 需要一个 vector<vector<Point>>
    polylines(image, std::vector<std::vector<Point>>{triangle}, true, Scalar(0, 0, 255), 2, LINE_AA);

    imshow("Polygon Example", image);
    waitKey(0);
    return 0;
}

输出结果如下所示:

填充多边形:cv::fillPoly

cpp 复制代码
void cv::fillPoly(
    cv::InputOutputArray img,
    const std::vector<std::vector<cv::Point>>& pts,
    const cv::Scalar& color,
    int lineType = LINE_8,
    int shift = 0,
    Point offset = Point()
);

示例:填充三角形

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat image = Mat::zeros(400, 400, CV_8UC3);

    std::vector<Point> triangle = { Point(50, 300), Point(200, 50), Point(350, 300) };
    
    fillPoly(image, std::vector<std::vector<Point>>{triangle}, Scalar(0, 255, 0));

    imshow("Filled Polygon Example", image);
    waitKey(0);
    return 0;
}

输出结果如下所示:

七、常用颜色速查表

注意:OpenCV 使用的是 BGR 顺序(不是 RGB)。

示例代码:

cpp 复制代码
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

// 宏:按直觉方式写 RGB(r,g,b)
#define RGB(r, g, b) cv::Scalar((b), (g), (r))

struct ColorDef {
    string name;
    Scalar color;
    int r, g, b;
};

// 全局变量
Mat img;
vector<Rect> colorBlocks;
vector<ColorDef> colors;

// 鼠标回调函数
void onMouse(int event, int x, int y, int, void*)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        for (size_t i = 0; i < colorBlocks.size(); i++)
        {
            if (colorBlocks[i].contains(Point(x, y)))
            {
                string info = colors[i].name + " RGB(" +
                              to_string(colors[i].r) + "," +
                              to_string(colors[i].g) + "," +
                              to_string(colors[i].b) + ")";
                cout << "You clicked: " << info << endl;

                // 修改窗口标题
							setWindowTitle("RGB Color Palette - " + info, "RGB Color Palette - " + info);
                break;
            }
        }
    }
}

int main()
{
    // 初始化颜色表
    colors = {
        {"Black",   RGB(0, 0, 0),       0,   0,   0},
        {"White",   RGB(255, 255, 255), 255, 255, 255},
        {"Red",     RGB(255, 0, 0),     255, 0,   0},
        {"Green",   RGB(0, 255, 0),     0,   255, 0},
        {"Blue",    RGB(0, 0, 255),     0,   0,   255},
        {"Yellow",  RGB(255, 255, 0),   255, 255, 0},
        {"Cyan",    RGB(0, 255, 255),   0,   255, 255},
        {"Magenta", RGB(255, 0, 255),   255, 0,   255},
        {"Gray",    RGB(128, 128, 128), 128, 128, 128},
        {"Orange",  RGB(255, 165, 0),   255, 165, 0},
        {"Pink",    RGB(255, 192, 203), 255, 192, 203},
        {"Brown",   RGB(139, 69, 19),   139, 69,  19}
    };

    int width = 900, height = 500;
    img = Mat(height, width, CV_8UC3, Scalar(255, 255, 255));

    int blockSize = 100; // 色块大小
    int margin = 20;     // 边距

    // 绘制调色板
    for (size_t i = 0; i < colors.size(); i++)
    {
        int row = i / 6;  // 每行 6 个
        int col = i % 6;

        int x = margin + col * (blockSize + margin);
        int y = margin + row * (blockSize + 80);

        Rect rect(x, y, blockSize, blockSize);
        colorBlocks.push_back(rect);

        // 绘制色块
        rectangle(img, rect, colors[i].color, FILLED);

        // 边框
        rectangle(img, rect, Scalar(0, 0, 0), 1);

        // 显示颜色名
        putText(img, colors[i].name, Point(x, y + blockSize + 25),
                FONT_HERSHEY_SIMPLEX, 0.6, Scalar(0, 0, 0), 2);

        // 显示 RGB 数值
        char rgbText[50];
        sprintf(rgbText, "(%d,%d,%d)", colors[i].r, colors[i].g, colors[i].b);
        putText(img, rgbText, Point(x, y + blockSize + 50),
                FONT_HERSHEY_SIMPLEX, 0.5, Scalar(50, 50, 50), 1);
    }

    // 显示窗口
    namedWindow("RGB Color Palette", WINDOW_AUTOSIZE);
    setMouseCallback("RGB Color Palette", onMouse, nullptr);

    imshow("RGB Color Palette", img);
    waitKey(0);
    return 0;
}

输出结果如下所示:

相关推荐
Wnq100726 小时前
如何在移动 的巡检机器人上,实现管道跑冒滴漏的视觉识别
数码相机·opencv·机器学习·计算机视觉·目标跟踪·自动驾驶
曾经的三心草14 小时前
OpenCV4-直方图与傅里叶变换-项目实战-信用卡数字识别
python·opencv·计算机视觉
luoganttcc14 小时前
在 orin 上 安装了 miniconda 如何使用 orin 内置的 opencv
人工智能·opencv·计算机视觉
JinchuanMaster14 小时前
cv_bridge和openCV不兼容问题
人工智能·opencv·计算机视觉
heisd_115 小时前
在编译opencv出现的问题
人工智能·opencv·计算机视觉
却道天凉_好个秋17 小时前
OpenCV(十一):色彩空间转换
人工智能·opencv·计算机视觉
zy_destiny19 小时前
【工业场景】用YOLOv8实现行人识别
人工智能·深度学习·opencv·算法·yolo·机器学习
黄晓魚20 小时前
双目三维重建-2双目系统标定
opencv·计算机视觉·机器视觉·三维视觉
却道天凉_好个秋1 天前
OpenCV(七):BGR
opencv·计算机视觉