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

OpenCV(十八):绘制文本

概述

在计算机视觉项目中,我们经常需要在图像上绘制文本,例如:

  • 显示识别结果(如检测类别、置信度);
  • 绘制图像说明或标注;
  • 动态视频帧文字叠加;
  • 制作视觉化报告。

OpenCV 提供了 cv2.putText() 函数,可快速在图像上绘制文本信息,支持多种字体、缩放、颜色、抗锯齿等属性。

cv2.putText() 函数

函数原型如下:

cv2.putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)
参数含义
img输入图像(支持彩色或灰度)
text需要显示的字符串
org文本左下角坐标 (x, y)
fontFace字体类型(如 cv2.FONT_HERSHEY_SIMPLEX
fontScale字体缩放因子(控制大小)
color文本颜色 (B, G, R)
thickness线条粗细
lineType线型(推荐 cv2.LINE_AA 抗锯齿)
bottomLeftOrigin若为 True,则文字从下向上绘制(一般为 False)

常用字体类型

常量名字体样式特点
cv2.FONT_HERSHEY_SIMPLEX无衬线字体最常用、清晰
cv2.FONT_HERSHEY_PLAIN简单小字体小尺寸显示
cv2.FONT_HERSHEY_DUPLEX双线条字体更平滑
cv2.FONT_HERSHEY_COMPLEX复杂字体较大、曲线更自然
cv2.FONT_HERSHEY_TRIPLEX三线条字体更醒目
cv2.FONT_HERSHEY_COMPLEX_SMALL复杂小字体小尺寸文字
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX手写体花体风格
cv2.FONT_HERSHEY_SCRIPT_COMPLEX手写复杂体更艺术化
cv2.FONT_ITALIC倾斜样式与其他字体组合使用

例如:

font = cv2.FONT_HERSHEY_SIMPLEX | cv2.FONT_ITALIC

示例

文本基本绘制

import cv2
import numpy as np# 创建白色画布
img = np.ones((500, 900, 3), dtype=np.uint8) * 255# 绘制不同字体的文本
cv2.putText(img, "FONT_HERSHEY_SIMPLEX", (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)
cv2.putText(img, "FONT_HERSHEY_PLAIN", (30, 110), cv2.FONT_HERSHEY_PLAIN, 2, (0, 128, 255), 2, cv2.LINE_AA)
cv2.putText(img, "FONT_HERSHEY_DUPLEX", (30, 160), cv2.FONT_HERSHEY_DUPLEX, 1.2, (0, 200, 0), 2, cv2.LINE_AA)
cv2.putText(img, "FONT_HERSHEY_COMPLEX", (30, 210), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)
cv2.putText(img, "FONT_HERSHEY_SCRIPT_COMPLEX", (30, 260), cv2.FONT_HERSHEY_SCRIPT_COMPLEX, 1.2, (255, 0, 255), 2, cv2.LINE_AA)
cv2.putText(img, "ITALIC STYLE", (30, 310), cv2.FONT_HERSHEY_SIMPLEX | cv2.FONT_ITALIC, 1.3, (128, 0, 255), 2, cv2.LINE_AA)# 显示
cv2.imshow("Text Drawing Example", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

文本大小与对齐技巧

import cv2
import numpy as np# 创建白色画布
img = np.ones((600, 900, 3), dtype=np.uint8) * 255# 通用字体设置
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1
thickness = 2
line_type = cv2.LINE_AA# 函数:绘制带边框文字(方便观察对齐位置)
def draw_text(img, text, pos, align="left", color=(0, 0, 0)):"""绘制文字并根据 align 对齐方式调整坐标"""(text_w, text_h), baseline = cv2.getTextSize(text, font, font_scale, thickness)x, y = posif align == "center":x -= text_w // 2elif align == "right":x -= text_w# 绘制文字矩形框cv2.rectangle(img, (x, y - text_h - baseline), (x + text_w, y + baseline), (220, 220, 220), 1)# 绘制文字cv2.putText(img, text, (x, y), font, font_scale, color, thickness, line_type)# ======================
# 1️⃣ 水平居中对齐示例
# ======================
(h, w) = img.shape[:2]
text1 = "Center Alignment Example"
(text_w, text_h), _ = cv2.getTextSize(text1, font, font_scale, thickness)center_x = w // 2
center_y = 150draw_text(img, text1, (center_x, center_y), align="center", color=(0, 0, 255))# 绘制参考中心线
cv2.line(img, (center_x, 0), (center_x, h), (0, 200, 0), 1)# ======================
# 2️⃣ 右对齐文本
# ======================
text2 = "Right Aligned Text"
right_x = w - 50
draw_text(img, text2, (right_x, 250), align="right", color=(255, 0, 0))# 绘制右对齐参考线
cv2.line(img, (right_x, 0), (right_x, h), (100, 100, 100), 1)# ======================
# 3️⃣ 左对齐文本
# ======================
text3 = "Left Aligned Text"
left_x = 50
draw_text(img, text3, (left_x, 350), align="left", color=(0, 128, 0))cv2.line(img, (left_x, 0), (left_x, h), (100, 100, 100), 1)# ======================
# 4️⃣ 多行自动换行(自适应宽度)
# ======================
def draw_multiline_text(img, text, pos, max_width=400, line_space=10, color=(0, 0, 0)):"""在给定宽度范围内自动换行显示文本"""words = text.split(" ")x, y = posline = ""for word in words:temp_line = line + word + " "(tw, th), _ = cv2.getTextSize(temp_line, font, font_scale, thickness)if tw > max_width:cv2.putText(img, line, (x, y), font, font_scale, color, thickness, cv2.LINE_AA)y += th + line_spaceline = word + " "else:line = temp_linecv2.putText(img, line, (x, y), font, font_scale, color, thickness, cv2.LINE_AA)text4 = "This is a multi-line text demonstration using OpenCV automatic line wrapping."
draw_multiline_text(img, text4, (50, 450), max_width=500, color=(128, 0, 128))# ======================
# 5️⃣ 显示结果
# ======================
cv2.putText(img, "Text Alignment Demo", (260, 40),cv2.FONT_HERSHEY_DUPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA)cv2.imshow("Text Size & Alignment Example", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

中文文本绘制

from PIL import ImageFont, ImageDraw, Image
import cv2
import numpy as np# 创建 OpenCV 图像
img = np.ones((400, 800, 3), np.uint8) * 255# 转换为 PIL 图像
img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))# 选择中文字体(需存在)
font = ImageFont.truetype("simhei.ttf", 40)  # 黑体
draw = ImageDraw.Draw(img_pil)# 绘制中文
draw.text((50, 100), "OpenCV 绘制中文文本示例", font=font, fill=(255, 0, 0, 0))
draw.text((50, 180), "支持字体、大小、颜色、透明度", font=font, fill=(0, 128, 0, 0))# 转回 OpenCV 格式
img = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)cv2.imshow("中文文本示例", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

文本透明叠加(Overlay)

import cv2
import numpy as np# 创建背景图像(可换成自己的图片)
img = cv2.imread(cv2.samples.findFile("Lenna.png"))  # 若无可改为自定义背景
if img is None:img = np.full((480, 640, 3), (60, 120, 200), np.uint8)  # 纯色背景h, w = img.shape[:2]# ========= 参数设置 =========
text = "OpenCV Transparent Text Overlay"
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1.2
thickness = 2
text_color = (255, 255, 255)  # 白色
bg_color = (0, 0, 0)          # 黑色背景
alpha_text = 0.9               # 文本不透明度
alpha_bg = 0.4                 # 背景透明度# ========= 计算文字大小 =========
(text_w, text_h), baseline = cv2.getTextSize(text, font, font_scale, thickness)
text_x = (w - text_w) // 2
text_y = (h + text_h) // 2# ========= 创建 Overlay 层 =========
overlay = img.copy()# 计算背景矩形范围
pad = 20
rect_x1 = text_x - pad
rect_y1 = text_y - text_h - pad
rect_x2 = text_x + text_w + pad
rect_y2 = text_y + pad# 限制边界(防止越界)
rect_x1 = max(rect_x1, 0)
rect_y1 = max(rect_y1, 0)
rect_x2 = min(rect_x2, w)
rect_y2 = min(rect_y2, h)# ========= 绘制半透明矩形背景 =========
cv2.rectangle(overlay, (rect_x1, rect_y1), (rect_x2, rect_y2), bg_color, -1)# ========= 将 overlay 与原图混合 =========
cv2.addWeighted(overlay, alpha_bg, img, 1 - alpha_bg, 0, img)# ========= 绘制文本(再单独叠加文字)=========
text_overlay = img.copy()
cv2.putText(text_overlay, text, (text_x, text_y),font, font_scale, text_color, thickness, cv2.LINE_AA)# 文本部分透明混合
cv2.addWeighted(text_overlay, alpha_text, img, 1 - alpha_text, 0, img)# ========= 显示结果 =========
cv2.imshow("Transparent Text Overlay", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

动态文本绘制(视频帧实时显示)

# 从摄像头或视频文件读取帧;
# 每帧实时绘制文本(时间、帧率、计数)
# 半透明背景叠加(防止文字难以看清)
# 支持淡入淡出(透明度动画)
# 自动居中或固定位置显示import cv2
import numpy as np
import time# 打开摄像头(或替换为视频路径)
cap = cv2.VideoCapture(0)# 字体设置
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1
thickness = 2
text_color = (255, 255, 255)
bg_color = (0, 0, 0)# 控制参数
alpha_bg = 0.5      # 背景透明度
alpha_text = 0.9    # 文本透明度
frame_count = 0
start_time = time.time()while True:ret, frame = cap.read()if not ret:breakframe_count += 1h, w = frame.shape[:2]# ==== 动态内容 ====elapsed = time.time() - start_timefps = frame_count / elapsedtext1 = f"Elapsed: {elapsed:6.2f}s"text2 = f"FPS: {fps:5.2f}"text3 = time.strftime("Time: %H:%M:%S", time.localtime())# ==== 绘制函数 ====def draw_overlay_text(img, text, pos, color, bg_color, alpha_bg, alpha_text):"""绘制半透明背景+文字"""(text_w, text_h), baseline = cv2.getTextSize(text, font, font_scale, thickness)x, y = pospad = 8overlay = img.copy()rect_x1, rect_y1 = x - pad, y - text_h - padrect_x2, rect_y2 = x + text_w + pad, y + pad# 绘制半透明矩形背景cv2.rectangle(overlay, (rect_x1, rect_y1), (rect_x2, rect_y2), bg_color, -1)cv2.addWeighted(overlay, alpha_bg, img, 1 - alpha_bg, 0, img)# 再叠加文字层text_overlay = img.copy()cv2.putText(text_overlay, text, (x, y), font, font_scale, color, thickness, cv2.LINE_AA)cv2.addWeighted(text_overlay, alpha_text, img, 1 - alpha_text, 0, img)# ==== 在不同位置绘制动态文本 ====draw_overlay_text(frame, text1, (20, 50), text_color, bg_color, alpha_bg, alpha_text)draw_overlay_text(frame, text2, (20, 100), text_color, bg_color, alpha_bg, alpha_text)draw_overlay_text(frame, text3, (20, 150), (255, 200, 0), bg_color, alpha_bg, alpha_text)# ==== 可选:动态淡入效果 ====alpha_dynamic = 0.5 + 0.5 * np.sin(time.time() * 2.0)overlay = frame.copy()cv2.putText(overlay, "Recording...", (w - 280, h - 40),cv2.FONT_HERSHEY_DUPLEX, 1.0, (0, 0, 255), 2, cv2.LINE_AA)cv2.addWeighted(overlay, alpha_dynamic, frame, 1 - alpha_dynamic, 0, frame)# ==== 显示结果 ====cv2.imshow("Dynamic Text Overlay", frame)# 按 ESC 退出key = cv2.waitKey(1)if key == 27:breakcap.release()
cv2.destroyAllWindows()

排版与背景框

# 多行排版(标题、副标题、信息行)
# 自动背景框尺寸计算
# 居中、左对齐排版示例
# 半透明背景支持
# 自动换行与边距控制import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import textwrap# =======================
# 创建背景图
# =======================
img_h, img_w = 600, 900
img = np.full((img_h, img_w, 3), (30, 60, 120), np.uint8)# =======================
# 文本内容
# =======================
title = "OpenCV 中文排版与背景示例"
subtitle = "多行排版、半透明背景、自动换行"
content = ("OpenCV 默认不支持中文显示,所以需要借助 Pillow 绘制中文。""通过结合 getbbox()、rectangle() 与 addWeighted(),""可以实现整齐排版、自动背景框、居中与左对齐等效果。"
)
bottom_text = "按 ESC 键退出"# =======================
# 样式参数
# =======================
font_path = "C:/Windows/Fonts/simhei.ttf"  # Windows 黑体,可根据实际修改
font_size_title = 32
font_size_subtitle = 24
font_size_content = 20
font_size_bottom = 18margin = 20
line_space = 8
x_start = 50
y_start = 80
alpha_bg = 0.5  # 背景透明度# =======================
# 辅助函数:获取文本尺寸
# =======================
def get_text_size(font, text):"""返回文本宽度和高度"""bbox = font.getbbox(text)width = bbox[2] - bbox[0]height = bbox[3] - bbox[1]return width, height# =======================
# 辅助函数:绘制文本块
# =======================
def draw_text_block(img, x, y, text_lines, font_path, font_size,text_color=(255,255,255), bg_color=(0,0,0),alpha_bg=0.5, line_space=8):"""在 img 上绘制带半透明背景的文本块text_lines: list[str]返回更新后的 img 和下一段文本的 y 坐标"""# 转 PILimg_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))draw = ImageDraw.Draw(img_pil)pil_font = ImageFont.truetype(font_path, font_size)# 计算背景框尺寸line_sizes = [get_text_size(pil_font, line) for line in text_lines]max_w = max([w for w,h in line_sizes])total_h = sum([h for w,h in line_sizes]) + line_space*(len(line_sizes)-1)x1, y1 = x - margin, y - marginx2, y2 = x + max_w + margin, y + total_h + margin# 防止越界x1 = max(0, x1)y1 = max(0, y1)x2 = min(img.shape[1], x2)y2 = min(img.shape[0], y2)# 绘制半透明背景overlay = img.copy()cv2.rectangle(overlay, (x1, y1), (x2, y2), bg_color, -1)cv2.addWeighted(overlay, alpha_bg, img, 1-alpha_bg, 0, img)# 绘制文字y_offset = yfor line, (lw, lh) in zip(text_lines, line_sizes):draw.text((x, y_offset), line, font=pil_font, fill=text_color)y_offset += lh + line_space# 转回 OpenCV 图像img = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)return img, y_offset + margin# =======================
# 绘制标题、副标题
# =======================
y_current = y_start
img, y_current = draw_text_block(img, x_start, y_current, [title],font_path, font_size_title, text_color=(255,255,255),bg_color=(0,0,0), alpha_bg=alpha_bg, line_space=line_space)
img, y_current = draw_text_block(img, x_start, y_current, [subtitle],font_path, font_size_subtitle, text_color=(255,200,100),bg_color=(0,0,0), alpha_bg=alpha_bg, line_space=line_space)# =======================
# 绘制正文,多行自动换行
# =======================
approx_char_per_line = 28
wrapped_lines = textwrap.wrap(content, width=approx_char_per_line)
img, _ = draw_text_block(img, x_start, y_current, wrapped_lines,font_path, font_size_content, text_color=(255,255,255),bg_color=(0,0,0), alpha_bg=alpha_bg, line_space=line_space)# =======================
# 底部提示文字
# =======================
img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_pil)
pil_font_bottom = ImageFont.truetype(font_path, font_size_bottom)
text_w, text_h = get_text_size(pil_font_bottom, bottom_text)
x_bottom = max(0, img_w - text_w - margin)
y_bottom = max(text_h + margin, img_h - 30)
draw.text((x_bottom, y_bottom), bottom_text, font=pil_font_bottom, fill=(180,220,255))
img = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)# =======================
# 显示结果
# =======================
cv2.imshow("中文排版与背景示例", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
http://www.dtcms.com/a/561227.html

相关文章:

  • Arbess实践指南(3) - 使用Arbess+sourcefare+PostIn实现Java项目自动化部署 + 代码扫描 + 接口自动化测试
  • 一,PCB介绍
  • 重庆网站建设机构科技进步是国防强大的重要的保证
  • asp网站用什么数据库做网站怎么导入源码
  • 【Docker】容器操作和实战
  • 阿里巴巴网站如何做免费推广wordpress首页文章轮播
  • 缓存三大问题及解决方案
  • 深度学习周报(10.27~11.2)
  • 怎么做便民信息网站原创小说手机网站制作需要多少钱
  • Java外功精要——Spring AOP
  • 线程从共享队列取任务的底层机制
  • 一站式网站建设报价怎样做商城网站
  • 宜春公司网站建设网页改进方案
  • 「经典数字题」集合 | C/C++
  • centos7实测
  • 【3DV 进阶-5】3D生成中 Inductive Bias (归纳偏置)的技术路线图
  • HOT100题打卡第26天——动态规划
  • 第五章 二项式系数
  • 制作网站语言网络营销方法有什么
  • 合肥网站建站推广从零开始做电影网站
  • 电商Web 渗透测试小小清单
  • 做信息流推广需要建立网站么最基本的网站设计
  • 基于双向时序卷积网络与门控循环单元(BiTCN-GRU)混合模型的时间序列预测MATLAB代码
  • DevOps(devops/k8s/docker/Linux)学习笔记-2
  • 三点水网站建设wordpress wp-polls
  • 用数据照亮成长之路:PandaCoder Git 统计工具窗口
  • FPGA的LVDS接口电压
  • 【每天一个AI小知识】:什么是Embedding?
  • 南昌网站排名优化免费提供空间的网站
  • 三种服务生命周期