utils.py
目录
下面按功能 → 关键逻辑 → 细节说明的方式,朴实地把这段代码拆开讲清楚。
1. 整体作用概述
主要做三件事:
- 根据原始图片路径生成“子故障图片”的新文件名
- (可选)在图片上画矩形框并保存
- 把生成的图片上传到 OBS
- 在已有图片上绘制中文说明文字(使用 PIL 解决中文乱码问题)
2. 依赖库说明
from PIL import Image, ImageDraw, ImageFont
import cv2
import os
from urllib.parse import unquote
import numpy as np
- cv2 / numpy:读写图片、画矩形
- PIL (Pillow):专门用来画中文(OpenCV 画中文很麻烦)
- unquote:防止路径中出现中文编码问题
- settings:配置目录(如图片保存路径)
- uploader:上传图片到 OBS
- process_logger:日志(本文件中未直接使用)
3. get_sub_fault_img_path_and_upload_obs
def get_sub_fault_img_path_and_upload_obs(img_source_path, error_code, draw=None, img_idx=1):
3.1 作用
- 生成子故障图片
- 上传到 OBS
- 返回生成的文件名
3.2 执行流程
- 调用
get_sub_fault_img_path生成图片并返回文件名 - 拼接成完整路径
- 调用
uploader(full_img_path)上传 - 返回文件名(而不是 OBS 路径)
fname = get_sub_fault_img_path(...)
if fname is not None:
full_img_path = ...
status, obs_path = uploader(full_img_path)
return fname
注意:
- 上传是否成功不影响返回值
- 返回的是本地文件名,不是 OBS 路径
4. get_sub_fault_img_path(核心函数)
def get_sub_fault_img_path(img_source_path, error_code, draw=None, img_idx=1):
4.1 解析原始图片文件名
img_fname = os.path.basename(img_source_path)
passtime, line, train, car, yard, direction, camera, fault_code = \
img_fname.replace(".jpg", "").split("_")
原始图片名格式示例:
AIzt_20250723053306000_M15_15021_06_yard_1_camera_102.jpg
解析得到:
- passtime:时间戳
- line:线路(M15)
- train:车号
- car:车厢号
- yard:场段
- direction:方向
- camera:相机
- fault_code:原始故障码
后面会把 line 转成小写(m15)
4.2 不画框(draw is None)
4.2.1 生成文件名
aizt_时间_线路_车号_车厢_场段_方向_相机_错误码_序号.jpg
示例:
aizt_20250723053306000_m15_15021_06_yard_1_camera_201_1.jpg
4.2.2 处理逻辑
- 拼完整保存路径
unquote防止中文路径乱码- 如果文件已存在:
img_idx + 1递归调用,避免覆盖
- 如果不存在:
- 使用
cv2.imdecode + np.fromfile读取图片。解决 Windows 中文路径 cv2.imread 失败的问题 - 保存图片
- 返回文件名
- 使用
img = cv2.imdecode(np.fromfile(img_source_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
cv2.imwrite(dinghan_img_save_fp, img)
4.3 画框模式(draw != None)
draw 格式:
(left, top, width, height)
4.3.1 文件名区别
..._errorcode_draw_序号.jpg
4.3.2 核心逻辑
- 判断文件是否存在,避免重名
- 读取原图
- 画红色矩形框
cv2.rectangle(
img,
(left, top),
(left + width, top + height),
(0, 0, 255),
3
)
- 保存并返回文件名
5. draw_tanhuakuai_chinese(中文标注)
5.1 作用
在已保存的图片上:
- 写中文说明文字
- 位置在矩形框上方
- 使用 PIL 解决 OpenCV 中文乱码
5.2 读取并转换格式
img = cv2.imread(img_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(img_rgb)
OpenCV → PIL(因为 PIL 才能稳定画中文)
5.3 设置字体
try:
font = ImageFont.truetype("./simhei.ttf", 36)
except:
font = ImageFont.load_default()
- 优先使用 黑体
- 字体不存在就降级(⚠️ 默认字体可能不支持中文)
5.4 计算文字位置
text = "受流器集电靴碳滑块厚度小于2毫米"
text_height = ...
text_x = left
text_y = top - text_height - 5
文本画在矩形框上方
5.5 绘制文字(带描边)
draw.text(
(text_x, text_y),
text,
font=font,
fill=(255, 0, 0),
stroke_width=2,
stroke_fill=(0, 0, 0)
)
- 红色文字
- 黑色描边
- 提高可读性
5.6 保存结果
img_with_text = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
cv2.imwrite(img_path, img_with_text)
直接覆盖原图
6. 几个设计上的细节总结
-
递归避免文件名冲突
img_idx + 1 -
cv2.imdecode + np.fromfile- 专门解决 Windows 中文路径问题
-
OpenCV + PIL 混合使用
- OpenCV:画框、性能好
- PIL:画中文、稳定
-
函数职责清晰
- 生成文件
- 上传 OBS
- 中文标注分离

浙公网安备 33010602011771号