|
发表于 2025-10-10 00:56:41
|
显示全部楼层
"""
这种方式可以处理中文等其它语言不会乱码
确保图像数据是uint8类型
如果PIL处理失败,自动回退到OpenCV方案
处理float32和float64数据类型
在try块内导入PIL,避免没有安装时崩溃
即使PIL有问题,代码也能正常工作,只是中文会显示为英文或乱码。如果确实需要中文支持,请确保安装了Pillow:
pip install Pillow
"""
import cv2
import numpy as np
def label_face_filename(face, filename):
# 1. 去除文件扩展名
filename_without_ext = filename.rsplit('.', 1)[0] if '.' in filename else filename
# 确保图像数据类型是uint8
if face.dtype != np.uint8:
if face.dtype == np.float32 or face.dtype == np.float64:
# 如果是float类型,假设范围是0-1,转换为0-255
face = (face * 255).astype(np.uint8)
else:
# 其他类型直接转换
face = face.astype(np.uint8)
# 根据图像大小自动调整
height, width = face.shape[:2]
face = face.copy()
# 尝试使用PIL处理中文,如果失败则回退到OpenCV
try:
from PIL import Image, ImageDraw, ImageFont
# 将OpenCV图像转换为PIL图像 (BGR to RGB)
pil_image = Image.fromarray(cv2.cvtColor(face, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(pil_image)
# 尝试加载中文字体
try:
font_paths = [
"C:/Windows/Fonts/simhei.ttf", # Windows 黑体
"C:/Windows/Fonts/simsun.ttc", # Windows 宋体
"/System/Library/Fonts/PingFang.ttc", # macOS
"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", # Linux
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", # Linux 文泉驿
]
font_size = max(12, int(height * 0.08))
font = None
for font_path in font_paths:
try:
font = ImageFont.truetype(font_path, font_size)
break
except:
continue
if font is None:
font = ImageFont.load_default()
except Exception as e:
font = ImageFont.load_default()
font_size = 12
# 计算文字位置和尺寸
try:
bbox = draw.textbbox((0, 0), filename_without_ext, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
except:
text_width, text_height = draw.textsize(filename_without_ext, font=font)
# 文字位置
x = 5
y = height - text_height - 5
if x + text_width > width:
x = max(0, width - text_width - 5)
# 智能选择文字颜色
bg_region_x1 = max(0, x - 3)
bg_region_y1 = max(0, y - 3)
bg_region_x2 = min(width, x + text_width + 3)
bg_region_y2 = min(height, y + text_height + 3)
bg_region = face[bg_region_y1:bg_region_y2, bg_region_x1:bg_region_x2]
if bg_region.size > 0:
avg_color = np.mean(bg_region, axis=(0, 1))
brightness = 0.299 * avg_color[2] + 0.587 * avg_color[1] + 0.114 * avg_color[0]
if brightness > 128:
text_color = (0, 0, 0)
bg_color = (255, 255, 255)
else:
text_color = (255, 255, 255)
bg_color = (0, 0, 0)
else:
text_color = (255, 255, 255)
bg_color = (0, 0, 0)
# 绘制半透明背景
bg_image = Image.new('RGB', (width, height), bg_color)
pil_image = Image.blend(pil_image, bg_image, alpha=0.6)
# 重新创建draw对象
draw = ImageDraw.Draw(pil_image)
draw.text((x, y), filename_without_ext, fill=text_color, font=font)
# 转换回OpenCV格式
face_labeled = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
return face_labeled
except Exception as e:
# 如果PIL处理失败,回退到OpenCV的英文显示
print(f" IL处理失败,使用OpenCV回退方案: {e}")
return label_face_filename_fallback(face, filename_without_ext)
def label_face_filename_fallback(face, filename):
"""OpenCV回退方案,只支持英文"""
# 确保图像数据类型是uint8
if face.dtype != np.uint8:
if face.dtype == np.float32 or face.dtype == np.float64:
face = (face * 255).astype(np.uint8)
else:
face = face.astype(np.uint8)
height, width = face.shape[:2]
# 计算合适的字体大小
base_font_scale = 0.4
font_scale = base_font_scale * (width / 128)
font_scale = max(0.3, min(font_scale, 1.0))
font = cv2.FONT_HERSHEY_SIMPLEX
thickness = max(1, int(font_scale * 2))
# 计算文字位置
text_size = cv2.getTextSize(filename, font, font_scale, thickness)[0]
org = (5, height - 10)
if org[0] + text_size[0] > width:
org = (max(0, width - text_size[0] - 5), org[1])
face = face.copy()
# 智能选择文字颜色
bg_region = face[org[1] - text_size[1] - 5 rg[1] + 5,
org[0] - 5 rg[0] + text_size[0] + 5]
if bg_region.size > 0:
avg_color = np.mean(bg_region, axis=(0, 1))
brightness = 0.299 * avg_color[2] + 0.587 * avg_color[1] + 0.114 * avg_color[0]
if brightness > 128:
text_color = (0, 0, 0)
bg_color = (255, 255, 255)
else:
text_color = (255, 255, 255)
bg_color = (0, 0, 0)
else:
text_color = (255, 255, 255)
bg_color = (0, 0, 0)
# 绘制背景
overlay = face.copy()
cv2.rectangle(overlay,
(org[0] - 3, org[1] - text_size[1] - 3),
(org[0] + text_size[0] + 3, org[1] + 3),
bg_color, -1)
alpha = 0.7
cv2.addWeighted(overlay, alpha, face, 1 - alpha, 0, face)
# 添加文字
cv2.putText(face, filename, org, font, font_scale, text_color, thickness, cv2.LINE_AA)
return face
|
|