opencv原生cv::puttext不支持中文,因其仅兼容ascii字符集且内置字体无中文字形;需借助windows gdi、freetype或pillow等方案实现中文渲染。

cv::putText 画文字的基本用法
直接调用 cv::putText 就能往 cv::Mat 上写文字,但必须确保图像不是空的、类型支持(如 CV_8UC3),且字体参数不传错。最常踩的坑是传了中文路径或 UTF-8 字符串——OpenCV 原生只支持 ASCII,cv::putText 遇到非 ASCII 字符会静默失败或显示方块。
基础调用示例:
cv::Mat img = cv::Mat::zeros(400, 600, CV_8UC3); cv::putText(img, "Hello", cv::Point(50, 100), cv::FONT_HERSHEY_SIMPLEX, 1.2, cv::Scalar(0, 255, 0), 2);
-
img必须已分配内存,不能是刚声明未初始化的空cv::Mat -
cv::FONT_HERSHEY_SIMPLEX是最常用字体,其他如cv::FONT_HERSHEY_PLAIN不支持粗细(thickness> 1 无效) -
cv::Scalar(0, 255, 0)是 BGR 顺序,不是 RGB;传错颜色可能看起来“没画出来” - 坐标
cv::Point(x, y)是文字**左下角**位置,不是左上角——y 值太小会导致文字被截断
中文显示必须绕过 cv::putText
OpenCV 官方 cv::putText 不解析 UTF-8 或 GBK,直接传 "你好" 会只显示第一个字节或乱码。真要显示中文,得自己处理字体渲染:
- 用
cv::freetype::createFreeType2()加载 .ttf 文件(需 OpenCV ≥ 4.5.2 且编译时启用了 freetype 支持) - 或者把文字先用 Qt / Skia / FreeType 单独渲染成灰度图,再用
cv::addWeighted或 ROI 拷贝进原图 - 更轻量的做法:用系统 API(如 Windows 的 GDI
TextOut)在内存 DC 上画字,再读回cv::Mat
如果只是临时调试,建议先用英文占位,确认布局和样式正确后再集成中文字体方案。
字体大小、粗细与图像分辨率的关系
fontScale 是相对值,实际像素大小取决于图像 DPI 和缩放比例。在高分屏或缩放后的 UI 窗口中,fontScale=1.0 可能显得极小;反过来,在 1080p 图上设 fontScale=3.0 又容易糊边。
-
thickness大于 1 时,字体边缘会变粗,但对cv::FONT_HERSHEY_PLAIN无效 - 抗锯齿靠
lineType=cv::LINE_AA开启,不加的话小字号文字边缘有明显锯齿 - 如果图像后续要 resize,建议先画字再缩放,否则
thickness和fontScale的视觉效果会失真
常见错误:文字不显示或位置偏移
最典型的三个原因:图像通道数不对、坐标越界、ROI 覆盖区域被意外修改。
- 传入单通道图(
CV_8UC1)却用三通道颜色cv::Scalar(0,255,0)→ 文字变成灰色甚至不可见 -
cv::Point(x, y)中 y 小于 0 或大于img.rows→ 文字完全消失(OpenCV 不报错) - 在
cv::Mat roi = img(cv::Rect(...))上调用putText,但 roi 是原图引用,坐标仍需按原图左上角计算 - 多线程环境下复用同一
cv::Mat且未加锁 → 文字偶尔错位或重叠
调试时先固定一个白色背景图、用大字号+红字+粗边框,确认基本通路跑通,再逐步还原真实参数。中文支持永远是最耗时的一环,别卡在第一步就怀疑 OpenCV 本身有问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











