OpenCV3 字体文字(putText()和 getTextSize())

本文介绍OpenCV中cv::putText()函数用于在图像上绘制文字的方法及cv::getTextSize()函数计算文字尺寸的功能。包括不同字体样式、文字位置设定及文字尺寸计算等关键细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

 

文字绘制函数
函数名称描述
cv::putText()在图像中绘制指定文字
cv::getTextSize()获取一个文字的宽度和高度

1  cv::putText()函数

/** @brief Draws a text string.

The function 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 cv::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 the line for details.
@param bottomLeftOrigin When true, the image data origin is at the bottom-left corner. Otherwise,
it is at the top-left corner.
 */
CV_EXPORTS_W void putText(
                         InputOutputArray img, 
                         const String& text, 
                         Point org,
                         int fontFace, 
                         double fontScale, 
                         Scalar color,
                         int thickness = 1, 
                         int lineType = LINE_8,
                         bool bottomLeftOrigin = false 
                        );

 

 这个函数是OpenCV的一个主要文字绘制方法,它可以简单地在图像上绘制一些文字,由text指定地文字将在以左上角为原点地文字框中以color指定地颜色绘制出来,除非bottomLeftOrigin标志设置为真,这种情况以左下角为原点,使用的字体由fontFace参数决定

可以使用的字体
标识符描述
 FONT_HERSHEY_SIMPLEX                   = 0!< normal size sans-serif font  普通大小无衬线字体
FONT_HERSHEY_PLAIN                         = 1!< small size sans-serif font     小号无衬线字体
FONT_HERSHEY_DUPLEX                     = 2!< normal size sans-serif font (more complex than FONT_HERSHEY_SIMPLEX)      普通大小无衬线字体
FONT_HERSHEY_COMPLEX                 = 3!< normal size serif font   普通大小无衬线字体比 FONT_HERSHEY_DUPLEX 更复杂
FONT_HERSHEY_TRIPLEX                    = 4 

!< normal size serif font (more complex than FONT_HERSHEY_COMPLEX  

普通大小无衬字体,比 FONT_HERSHEY_COMPLEX 更复杂

  FONT_HERSHEY_COMPLEX_SMALL = 5

!< smaller version of FONT_HERSHEY_COMPLEX

小号版本的  FONT_HERSHEY_COMPLEX

FONT_HERSHEY_SCRIPT_SIMPLEX   = 6!< hand-writing style font     手写字体
FONT_HERSHEY_SCRIPT_COMPLEX = 7

!< more complex variant of FONT_HERSHEY_SCRIPT_SIMPLEX

比 FONT_HERSHEY_SCRIPT_SIMPLEX  更复杂的变体

FONT_ITALIC                                          = 16!< flag for italic font  

 

表中列出来的任何一个字体都可以和CV::FONT_ITALIC 组合使用(通过或操作)来得到斜体。每种字体都有一个“自然”大小,当fontScale不是1.0时,在文字绘制之前字体大小将由这个数缩放。

#include<iostream>
#include<opencv2\core.hpp>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
const char *path1 = "D:/Coder/vs/1_OpenCV/3096.jpg";

int main()
{
	cv::Mat img = cv::imread(path1,cv::IMREAD_UNCHANGED);
	const std::string str1 = "Hello World!";
	cv::putText(img, str1, cv::Point2i(0, 0), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 30), cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 60), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 90), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 120), cv::FONT_HERSHEY_TRIPLEX, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 150), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 180), cv::FONT_HERSHEY_SCRIPT_SIMPLEX, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 210), cv::FONT_HERSHEY_SCRIPT_COMPLEX, 1, cv::Scalar(0, 255, 230), 1, 8, false);
	cv::putText(img, str1, cv::Point2i(0, 250), cv::FONT_ITALIC|cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(0, 255, 230), 1, 8, false);

	cv::imshow("1", img);
	cv::waitKey(0);
	return 0;
}

 

衬线指的是字母结构笔画之外的装饰性笔画。有衬线的字体叫衬线体(serif);没有衬线的字体,则叫做无衬线体(sans-serif)。

衬线字体(serif)

特征:在字的笔画开始、结束的地方有额外的装饰,而且笔画的粗细会有所不同

用途:serif字体容易识别,它强调了每个字母笔画的开始和结束,因此易读性比较高。在整文阅读的情况下,适合使用serif字体进行排版,易于换行阅读的识别性,避免发生行间的阅读错误。

中文字体中的宋体就是一种最标准的serif字体,衬线的特征非常明显。字形结构也和手写的楷书一致。因此宋体一直被做为最适合的正文字体之一。

 

无衬线字体(sans-serif)

特征:sans serif是无衬线字体,没有这些额外的装饰,而且笔画的粗细差不多。该类字体通常是机械的和统一线条的,它们往往拥有相同的曲率,笔直的线条,锐利的转角。

用途:无衬线字体醒目,适合用于标题、DM、海报等,需要醒目但不需要长时间阅读的地方。但现在市场上很多app正文都开始采用无衬线字体,因为无衬线字体更简约、清新,比较有艺术感。

无衬线字体与汉字字体中的黑体相对应。为了起到醒目的作用,笔画比较粗,不适合长时间阅读,不适合用作正文字体。但是现代的 Macintosh、iOS、Android、Windows Vista 以上 等系统默认使用的无衬线字体基本上都是基于细黑体演化而来,不再像传统的无衬线字体那么重,因此用作正文字体时易读性也很高。

在传统的正文印刷中,普遍认为衬线体能带来更佳的可读性。尤其是在大段落的文章中,衬线增加了阅读时对字母的视觉参照。而无衬线体往往被用在标题、较短的文字段落或者一些通俗读物中。相比严肃正经的衬线体,无衬线体给人一种休闲轻松的感觉。随着现代生活和流行趋势的变化,如今的人们越来越喜欢用无衬线体,因为他们看上去“更干净”。

 2  cv::getTextSize() 函数

/** @brief Calculates the width and height of a text string.

The function getTextSize calculates and returns the size of a box that contains the specified text.
That is, the following code renders some text, the tight box surrounding it, and the baseline: :
@code
    String text = "Funny text inside the box";
    int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;
    double fontScale = 2;
    int thickness = 3;

    Mat img(600, 800, CV_8UC3, Scalar::all(0));

    int baseline=0;
    Size textSize = getTextSize(text, fontFace,
                                fontScale, thickness, &baseline);
    baseline += thickness;

    // center the text
    Point textOrg((img.cols - textSize.width)/2,
                  (img.rows + textSize.height)/2);

    // draw the box
    rectangle(img, textOrg + Point(0, baseline),
              textOrg + Point(textSize.width, -textSize.height),
              Scalar(0,0,255));
    // ... and the baseline first
    line(img, textOrg + Point(0, thickness),
         textOrg + Point(textSize.width, thickness),
         Scalar(0, 0, 255));

    // then put the text itself
    putText(img, text, textOrg, fontFace, fontScale,
            Scalar::all(255), thickness, 8);
@endcode

@param text Input text string.
@param fontFace Font to use, see cv::HersheyFonts.
@param fontScale Font scale factor that is multiplied by the font-specific base size.
@param thickness Thickness of lines used to render the text. See putText for details.
@param[out] baseLine y-coordinate of the baseline relative to the bottom-most text
point.
@return The size of a box that contains the specified text.

@see cv::putText
 */
CV_EXPORTS_W Size getTextSize(const String& text, int fontFace,
                            double fontScale, int thickness,
                            CV_OUT int* baseLine);

参数意义

. const string& text: 输入的文本文字 
. int fontFace: 文字字体类型 
. double fontScale: 字体缩放系数 
. int thickness: 字体笔画线宽 
. CV_OUT int* baseLine: 文字最底部y坐标

cv::getTextSize()函数回答了如果把文字绘制出来将有多大的问题,而不用实际将文字绘制到图上,cv::getTextSize()唯一的新的参数就是baseLine,这实际上是一个输出参数,baseLine是和文字最低点相关的文字基线的y坐标值。

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include<opencv2\imgproc.hpp>

using namespace std;
using namespace cv;

int main()
{
	string text = "Funny text inside the box";
	//int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;     //手写风格字体
	int fontFace = FONT_HERSHEY_SCRIPT_COMPLEX;
	double fontScale =2;       //字体缩放比
	int thickness = 3;

	Mat img(600, 800, CV_8UC3, Scalar::all(0));

	int baseline = 0;

	Size textSize = getTextSize(text, fontFace, fontScale, thickness, &baseline);
	baseline += thickness;
	//center the text
	Point textOrg((img.cols - textSize.width) / 2, (img.rows - textSize.height) / 2);
	//draw the box
	rectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0, 0, 255));
	line(img, textOrg + Point(0, thickness), textOrg + Point(textSize.width, thickness), Scalar(0, 0, 255));
	putText(img, text, textOrg, fontFace, fontScale, Scalar::all(255), thickness, 8);
	imshow("text", img);
	waitKey(0);
	return 0;
}

 

<think>好的,我现在需要帮助用户了解如何在OpenCV中向图片添加文字并设置字体颜色。首先,我应该回忆一下OpenCV的相关函数,特别是关于文本绘制的部分。记得OpenCV有一个cv::putText函数,但可能不支持所有字体,默认的字体可能比较有限。 用户提到的是字体颜色自定义,所以需要确认putText的参数中颜色是如何设置的。颜色通常是通过Scalar对象来指定的,比如Scalar(B, G, R),这里需要注意颜色通道的顺序是否是BGR,因为OpenCV默认使用BGR格式。 接下来是字体的问题,用户可能想要使用不同的字体样式,而不仅仅是OpenCV自带的几种。这时候可能需要用到Hershey字体集,这些字体OpenCV内置的,通过参数来选择,比如FONT_HERSHEY_SIMPLEX。但用户如果希望使用系统字体或其他自定义字体,可能需要其他方法,比如使用FreeType库,但OpenCV本身可能不直接支持,需要额外的模块或者自己实现。 然后,我需要检查OpenCVputText函数的具体参数。函数原型大致是putText(img, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin)。其中fontFace参数决定了字体类型,color是Scalar,fontScale控制字体大小,thickness是线条粗细。 关于颜色设置,用户可能希望动态调整颜色,例如根据背景变化,或者使用不同的颜色组合。这时候需要确保用户传入正确的BGR值,例如红色是(0,0,255),蓝色是(255,0,0)等。同时,可能需要提醒用户注意颜色通道的顺序,避免常见的错误。 另外,文字的位置org参数是文本左下角的坐标,这一点需要明确,用户可能需要调整坐标来正确放置文本的位置。如果用户需要更复杂的排版,比如居中或右对齐,可能需要手动计算文本的宽度高度,这可以通过getTextSize函数来获取。 对于字体文件的支持,如果用户想使用TrueType字体或其他系统字体,可能需要使用cv::freetype::FreeType2库,这个属于OpenCV的contrib模块,需要额外安装配置。这时候需要指导用户如何编译带有freetype支持的OpenCV,或者使用其他方法。 总结步骤应该是:导入OpenCV库,读取图片,使用putText函数,设置字体类型、大小、颜色、位置等参数,然后保存或显示图片。示例代码可能会帮助用户更直观地理解,比如: import cv2 img = cv2.imread(&#39;image.jpg&#39;) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img, &#39;Hello World&#39;, (50,50), font, 1, (0,255,0), 2) cv2.imwrite(&#39;output.jpg&#39;, img) 这样,用户就能看到绿色的文字添加到图片上。同时,需要提醒用户注意坐标系统是从左上角开始的,y轴向下,这可能常见的图形系统不同。 可能的问题还包括,如何处理中文等非ASCII字符,这时候可能需要使用其他库如PIL(Python Imaging Library)结合OpenCV,因为OpenCVputText可能不支持Unicode字符。这种情况下,可能需要额外的步骤,比如将图像从BGR转换为RGB,使用PIL绘制文本,再转换回来。 此外,性能方面,如果用户需要频繁添加文字,或者处理大量图片,可能需要考虑代码的效率,但一般情况下putText的性能已经足够好。 最后,应该检查是否有相关的引用或资料需要提及,比如OpenCV的官方文档,或者某些教程链接,但根据用户提供的引用,目前没有直接相关的,但可能需要提到OpenCV的samples中的示例代码,如引用[1]提到的官方demo工程,可能包含相关示例。 用户可能还会想知道如何调整字体的大小、粗细,或者添加阴影效果等,这些可以通过调整fontScale、thickness参数,或者多次绘制文本来实现。例如,先绘制一个较粗的黑色文本作为阴影,再在上面绘制较细的彩色文本,来模拟阴影效果。 综上所述,回答应该分步骤说明,如何用putText函数添加文字,如何设置颜色,字体类型,位置等,并给出示例代码。同时,提及字体的限制可能的扩展方法,比如使用FreeType模块,或者结合其他库处理复杂字体需求。</think>### 如何在 OpenCV 中向图片插入文字并设置字体颜色? #### 步骤说明 1. **导入 OpenCV 库** 确保已安装 OpenCV(Python 中为 `opencv-python` 包),并导入库: ```python import cv2 ``` 2. **读取图片** 使用 `cv2.imread()` 加载图片,支持常见格式(如 JPG、PNG): ```python image = cv2.imread("input.jpg") # 替换为实际路径 ``` 3. **设置字体参数** OpenCV 提供了几种内置的 Hershey 字体(例如 `FONT_HERSHEY_SIMPLEX`),通过 `cv2.FONT_*` 指定。颜色使用 BGR 格式的元组 `(B, G, R)`,例如红色为 `(0, 0, 255)`。其他参数: - `fontScale`: 字体缩放比例(1 为原始大小) - `thickness`: 文字粗细(像素) 4. **添加文字** 使用 `cv2.putText()` 函数将文字绘制到图片上: ```python text = "Hello OpenCV" position = (50, 50) # 文字左下角坐标(x, y) font = cv2.FONT_HERSHEY_SIMPLEX color = (0, 255, 0) # 绿色 cv2.putText(image, text, position, font, 1.0, color, 2) ``` 5. **保存或显示结果** 输出处理后的图片: ```python cv2.imwrite("output.jpg", image) # 保存到文件 # 或者直接显示 cv2.imshow("Text Added", image) cv2.waitKey(0) ``` #### 完整示例代码 ```python import cv2 # 读取图片(若图片路径错误,会返回 None) image = cv2.imread("input.jpg") if image is None: print("Error: 图片加载失败") else: # 设置文字参数 text = "OpenCV Demo" position = (100, 150) font = cv2.FONT_HERSHEY_SIMPLEX color = (0, 0, 255) # 红色 thickness = 2 # 添加文字 cv2.putText(image, text, position, font, 1.5, color, thickness) # 保存结果 cv2.imwrite("output_with_text.jpg", image) print("文字添加成功") ``` #### 注意事项 1. **字体限制** OpenCV 原生仅支持 Hershey 字体[^1],若需更多字体(如 TrueType),需使用 `cv2.freetype` 模块(需安装 OpenCV contrib 版本): ```python import cv2 ft = cv2.freetype.createFreeType2() ft.loadFontData(fontFileName="arial.ttf", id=0) ft.putText(image, "Custom Font", (50,50), 30, (255,0,0), thickness=1, line_type=cv2.LINE_AA, bottomLeftOrigin=True) ``` 2. **中文支持** 原生 `cv2.putText()` 不支持中文,可通过以下方法实现: - **方法 1**:结合 PIL 库(推荐) ```python from PIL import ImageFont, ImageDraw, Image import numpy as np # 将 OpenCV 图像转换为 PIL 格式 image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(image_pil) font = ImageFont.truetype("msyh.ttf", 20) # 微软雅黑字体 # 绘制中文 draw.text((50, 50), "你好,世界!", font=font, fill=(255, 0, 0)) # 转换回 OpenCV 格式 image = cv2.cvtColor(np.array(image_pil), cv2.COLOR_RGB2BGR) ``` - **方法 2**:使用 OpenCV contrib 的 FreeType 模块(需编译安装)[^2]。 3. **颜色与坐标系统** - 颜色顺序为 **BGR**(非 RGB),例如蓝色为 `(255, 0, 0)`。 - 坐标系原点在图片左上角,`(x, y)` 中 `x` 向右增长,`y` 向下增长。 #### 扩展优化 - **动态调整文字位置**:通过 `cv2.getTextSize()` 获取文字占用的像素范围,实现居中或自适应布局。 - **阴影效果**:绘制两次文字,第一次用深色粗线条作为背景,第二次用浅色细线条作为前景。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

&小鹏鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值